DefaultJ is a Java library to provide a default value of any class. It support multiple strategies of getting the default value. It can be use as a simple but powerful dependency injection utility. In that aspect, it injects value base on the class, very much similar in principle with Guice.
public class Car {
@Default
public static Car newInstance() { return new Car(); }
public String go() {
return "Zoom!";
}
}
public class Driver {
private Car car;
public Driver(Car car) {
this.car = car;
}
public String drive() {
return car.go();
}
}
...
Car myCar = DefaultProvider.instance.get(Car.class);
assertEquals("Zoom!", myCar.go());
Driver myDriver = DefaultProvider.instance.get(Driver.class);
assertEquals("Zoom!", myDriver.drive());
As you can see, DefaultJ can get default values of the Car
and Driver.
In case of Car
, since there is @Default
on a static method that return Car
, DefaultJ use that to create an instance.
In case of Driver
, its has a constructor requiring a Car
instance so DefaultJ create a Car
instance and use that to create a Driver
instance.
Calling default constructor is one of the strategy DefaultJ uses.
Factory method is another strategy.
DefaultJ has 14 built-in strategies for getting default values.
More detail about those strategies are discussed below.
It is important to note that DefaultJ does not require the annotation @Default
to be
from DefaultJ.
The annotation can be from any package.
It just has to have RUNTIME
retention.
This allow any code to specify default value providing strategy without depending on DefaultJ.
There are strategies DefaultJ deploys to obtain a default value. Calling the default constructor is just one of such strategies. With the help of a few annotations, DefaultJ will try different strategy to obtains the default value. The followings are the strategies in order that DefaultJ attempts. If the any strategy is not applicable, DefaultJ will skip it to the next one.
- Bindings -- Explicit binding of how the value is obtained.
- @DefaultImplementation -- specify a class name for the be used as default (only if in the classpath).
- @ImplementationBy -- specify a class that is the default implementation.
- Enum value -- default value for enum.
- @DefaultInterface -- specify that all methods in the interface are default methods.
- Additional finder -- additional strategies.
- Singleton field -- a public static final field in the class that hold the default value.
- Factory method -- a public static final method in the class that return the default value.
- @DefaultToNull -- specify that the default for this class is
null
. - @Default on constructor -- specify the default constructor to use.
- Only constructor -- use the only constructor.
- Default constructor -- use the default constructor (the constructor with no argument).
- KnowNullValue -- NullableJ known null value.
- KnownNewValue -- NullableJ known new value.
As mentioned, DefaultJ check for annotations for more clue on how to provide default, there are a few points to be noted on annotation used with DefaultJ.
- All the annotation is defined in DefaultJ's Annotations package.
- DefaultJ check the annotation by name so you don't need to use the provided annotation. If desired, you can created and use yourown annotations. The name just have to match and the retention policy must be specified to Runtime (RetentionPolicy.RUNTIME). See many unit tests for example.
- Annotation processors to validate the use of annotation are available in DefaultJ's Annotations package.
Consult your IDE/build system on how to enable that.
The supported validations are:
- @Default on methods/fields must be for
public
static
andfinal
, - @DefaultInterface must be on an interface with all default methods,
- @ImplementationBy must contains the class that exists and compatible with the annotated class.
- @Default on methods/fields must be for
This project binary is published on Maven Central. So to use DefaultJ you will need to add the dependencies to DefaultJ (Gradle 5.0).
compile 'io.defaultj:defaultj-core:2.0.0.0' // Please lookup for the latest version.
compile 'io.defaultj:defaultj-annotation:2.0.0.0' // Please lookup for the latest version.
annotationProcessor 'io.defaultj:defaultj-annotation:2.0.0.0' // Please lookup for the latest version.
UseNullableJGradle is an example project that use NullableJ. You can use that as a starting point. Just add the dependency to DefaultJ to it.
Add the dependencies to DefaultJ.
<dependency>
<groupId>io.defaultj</groupId>
<artifactId>defaultj-annotations</artifactId>
<version>2.0.0.0</version>
</dependency>
<dependency>
<groupId>io.defaultj</groupId>
<artifactId>defaultj-core</artifactId>
<version>2.0.0.0</version>
</dependency>
UseNullableJMaven is an example project that use NullableJ. You can use that as a starting point. Just add the dependency to DefaultJ to it.
This project is developed as a gradle project on Eclipse
so you can just clone and import it to your Eclipse.
Although, never tried, but I think it should be easy to import into IntelliJ.
Simply run gradle clean build
to build the project (or use the build-in gradle wrapper).
The versioning of this project is not the commonly used semantic versioning. Well, the last three digits are kind of semantic version. But the first one represents a conceptual version of the library. This is done this way as it was found that the version was updates too quickly and there is nothing indicates the fundamental change in concept or philosophy of the library.
- The first digit is the version of the concept - changed when there is a big changes across the library or in the fundamental ways.
- The second digit is the version of the API - changed when there is a breaking changes in the API.
- The third digit is the version of the implementation.
- The forth digit is the version of correction.
Please use our issues tracking page to report any issues.
You can import and use this library as you needed. But if you just need a small part of it, feel free to fork it or just copy the part that you need. :-)
Feel free to join in. Report problems, suggest solutions, suggest more functionalities, making pull requests ... anything is appreciated (please do it in issues tracking page or email me directly).