SMOG Javassist Proxy Generator

SMOG extension for generating runtime matcher implementations from interfaces.

License

License

Categories

Categories

Javassist Application Layer Libs Bytecode Manipulation
GroupId

GroupId

com.mistraltech.smog
ArtifactId

ArtifactId

smog-javassist
Last Version

Last Version

1.0.0
Release Date

Release Date

Type

Type

jar
Description

Description

SMOG Javassist Proxy Generator
SMOG extension for generating runtime matcher implementations from interfaces.
Project URL

Project URL

https://github.com/mistraltechnologies/smog-javassist
Source Code Management

Source Code Management

https://github.com/mistraltechnologies/smog-javassist

Download smog-javassist

How to add to project

<!-- https://jarcasting.com/artifacts/com.mistraltech.smog/smog-javassist/ -->
<dependency>
    <groupId>com.mistraltech.smog</groupId>
    <artifactId>smog-javassist</artifactId>
    <version>1.0.0</version>
</dependency>
// https://jarcasting.com/artifacts/com.mistraltech.smog/smog-javassist/
implementation 'com.mistraltech.smog:smog-javassist:1.0.0'
// https://jarcasting.com/artifacts/com.mistraltech.smog/smog-javassist/
implementation ("com.mistraltech.smog:smog-javassist:1.0.0")
'com.mistraltech.smog:smog-javassist:jar:1.0.0'
<dependency org="com.mistraltech.smog" name="smog-javassist" rev="1.0.0">
  <artifact name="smog-javassist" type="jar" />
</dependency>
@Grapes(
@Grab(group='com.mistraltech.smog', module='smog-javassist', version='1.0.0')
)
libraryDependencies += "com.mistraltech.smog" % "smog-javassist" % "1.0.0"
[com.mistraltech.smog/smog-javassist "1.0.0"]

Dependencies

compile (2)

Group / Artifact Type Version
com.mistraltech.smog : smog-core jar 1.1.0
org.javassist : javassist jar 3.18.2-GA

test (4)

Group / Artifact Type Version
junit : junit jar 4.11
org.hamcrest : hamcrest-library jar 1.3
org.mockito : mockito-all jar 1.9.5
ch.qos.logback : logback-classic jar 1.1.1

Project Modules

There are no modules declared in this project.

smog-javassist

Javassist-based runtime code generator extension for Smog.

Summary

Matcher classes based on the SMOG Matcher library are typically boiler-plate code.

To avoid the burden of writing these, static code generators such as the Smogen IntelliJ plugin can be used. However, this still results in a lot of code that is baggage in a project.

Smog-Javassist is an extension to SMOG that removes the need for boiler-plate code without resorting to a reflection-oriented solution, so that the benefits of statically typed code are retained: type-safety and IDE-supported code completion and refactorings. It allows matchers to be written as interfaces only, with the implementation being generated at runtime using Javassist.

Usage Examples

Begin by creating an interface containing the matcher methods you want:

@Matches(value = Person.class, description = "a Person")
public interface PersonMatcher {

    PersonMatcher hasName(String name);

    PersonMatcher hasName(Matcher<? super String> nameMatcher);

    PersonMatcher hasAddress(Address address);

    PersonMatcher hasAddress(Matcher<? super Address> addressMatcher);
    
    PersonMatcher hasAge(int age);

    PersonMatcher hasAge(Matcher<? super Integer> ageMatcher);

    PersonMatcher hasPhoneList(Matcher<? super List<? extends Phone>> phoneListMatcher);
}

The @Matches annotation is required. It tells the code generator what class the matcher accepts and how to describe an instance of that class.

Then in your test, import the 'matcherOf' factory method and instantiate a matcher like this:

import static com.mistraltech.smog.proxy.javassist.JavassistMatcherGenerator.matcherOf;

...
    Matcher<Person> pm = matcherOf(PersonMatcher.class);
...

More commonly, you would instantiate the matcher within a Hamcrest assertion, such as:

assertThat(bob, matcherOf(PersonMatcher.class).hasName("Bob"));

The readability of this assertion can be further improved by writing a factory method for your matcher:

import static com.mistraltech.smog.proxy.javassist.JavassistMatcherGenerator.matcherOf;

public final class MatcherFactory {
    public static PersonMatcher aPersonThat() {
        return matcherOf(PersonMatcher.class);
    }
}

Given the above factory method and the gratuitous use of Hamcrest's is() method, the above assertion can then be rewritten as:

assertThat(bob, is(aPersonThat()).hasName("Bob"));

Notice that the PersonMatcher interface shown previously provides overloaded functions for each property: one that takes a value that is the same type as the matched property, and one that takes a Matcher. The code generator will generate appropriate implementations for both signatures. This allows other Hamcrest matchers to be used as parameters (including other SMOG matchers):

import static org.hamcrest.CoreMatchers.startsWith;

...
    assertThat(bob, is(aPersonThat()).hasName(startsWith("B")));
...

For more involved usage examples, see the tests in the library source code tree.

com.mistraltech.smog

Mistral Technologies Limited

Software development services provider.

Versions

Version
1.0.0