SpringOne: Modern Java Component Design with Spring 4.2

Reading Time: 6 minutes

Jurgen Holler and Stephane Nicoll’s SpringOne talk toured the annotations available to enhance the design of our classes in Spring.

Mr. Holler started off with an example service class. We walked through some of the Spring annotations used in it:

@Service — a version of the @Component annotation called a stereotype: it serves to inform developers that this is specifically a component of the service type.
@Autowired — When placed on top of a constructor, allows automatic dependency injection. (Sidenote: on top of the class itself, allows field injection).
@Transactional — A declarative annotation for tapping into a middleware service

Then, things got more advanced. We talked about some of the features of Spring annotations that give developers control over the structure and design of their applications.

spring

Custom Annotations

In addition to using the annotations that come with Spring, you can define your own custom annotations. Say, for example, you use the same three annotations on top of many of your classes, and you want to combine them into a custom one called @CombinedAnnotation.

Declare like so:

@Service
@Primary
@Scope(“session”)
public @interface CombinedAnnotation {}

To add overridable attributes to your custom annotation, you can define those overridable attributes inside the custom annotation interface.

Examples that one might put inside their custom annotation interface:

ScopedProxyMode proxyMode() default ScopedProxyMode.NO;

boolean readOnly() (this one has no default, so developers will be required to specify true or false).

Annotate this with @AliasFor(annotation=Transactional.class, attribute=”readOnly”) to be able to name that attribute anything you want, instead of having to explicitly name it readOnly() after the actual attribute.

Configuration Classes:

A configuration class specifically contains @Bean methods to declare the beans for a Spring app’s classes.

@Configuration
public class Configuration {

@Bean
public SomeService someService() {
SomeService service = new SomeService();
service. setDataSource(someDataSource());
return service;
}
}

Configuration classes can also extend base classes with abstract methods that must be implemented in subclass configurations or concrete methods that the configuration subclass can override.

Instead of a configuration base class, you can also create configuration interface with abstract methods or default methods (in Java 8) on them. This allows a configuration class to implement as many configuration interfaces as it needs.

Other annotations give developers even more control over their injections. For example, if certain classes are dependent on others and need to be instantiated in a certain order, developers can make this explicit with @Order annotations. Something annotated with @Order(1) will be instantiated before something annotated with @Order(2). These can be used in configuration classes as well as other classes.

Generics-Based Injection Matching

YAY! So now, if you have two beans,

@Bean
public SomeRepo<Thing> myThingRepo() {…}

@Bean
public SomeRepo<OtherThing> myOtherThingRepo() {…}

And a constructor like this:

@Autowired
public SomeService(SomeRepo<Thing> thingRepo){…}

Spring 4 will automatically resolve this, as opposed to complaining that there is no unique match for injection here.

As the talk continued, Mr. Holler began to speed up. We ran through several more examples of annotation use in Spring 4, including some Java 8-specific capabilities. This part of the talk went very fast, but the example code may be all developers need in many cases for muddling through getting these things to work. If the example code alone is not enough, I suggest some resources below to learn more about Spring annotations like these.

Lazy Injection Points

public SomeService(@Lazy MyRepo<Thing> thingRepo){…}

turns thingRepo into a lazy-initializing proxy. This is valuable in the case that thingRepo is not fully initialized at runtime, but isn’t needed yet.

Component Declarations with JSR-250 and JSR-330

Spring plays well with outside annotations like @ManageBean or @Inject (which one might use in exchange for @Autowired in some cases).

Optional Injection Points on Java 8

@Inject
public SomeService(Optional someDependency){
if(someDependency != null){…}
}

Now, if a dependency may or may not be needed in a component, Spring 4 allows use of the Java 8 optional annotation.

Declarative Formatting in Java 8: Date-Time

Rather than re-formatting dates manually, we can specify how we want date-times to appear via annotation.

//@DateTimeFormat(iso=ISO.DATE)
The above is actually the default behavior, so you don’t even need the annotation in the most up-to-date Date-Time package.
private LocalDate birthDate

@DateTimeFormat(pattern=”M/d/yy h:mm’)
@NotNull @Past
private LocalDateTime lastContact;

Money and Currency

Similar formatting conveniences exist for money and currency. Example:

@NumberFormat(pattern=’#000.000#’)
private MonetaryAmount netPrice;

Declarative Scheduling (with Java 8)

@Async
public CompletableFuture<Integer> sendEmailNotification(){
return CompleteableFuture.completedFuture(…);
}

@Scheduled(cron=”0 0 12 * * ?”)
@Scheduled(cron=”0 0 12 * * ?”)
//Java 8 allows repeat annotations on top of a method.
public void performTenpFileCleanup() {…}

Annotated Event Listeners

@EventListener(condition=’response.startsWith(‘OK’)’)
public void handleOkResponse(){…}

Annotated MVC Controllers

The above new annotations will work in the upcoming Spring release candidate in addition to classic annotations like those that drive the controller classes of a canonical spring app:

@RestController
@CrossOrigin
public class SomeController {

@RequestMapping(value=”/books/id”, method-GET)
public book findBook(@PathVariable long id){
return this.bookAdminService.findBook(id);
}

@RequestMapping(value=”/books/new”)
public void newBook(@Valid Book book){
return this.bookAdminService.newBook(book);
}
}

In total, the talk offered an interesting, if somewhat quick, introduction to some of the possibilities that Spring (and specifically Spring 4.2 with Java 8) provides for creating flexible Spring app component designs.

For more information about these annotations and others in the Spring framework, I highly recommend the following resources. They tend to be some of the first places to look for comprehensive guidance on the most up-to-date features in Spring:

If you are newer to Spring and you want to learn how to use its existing functionality to create a RESTful app, I found the Spring REST book to be an approachable introduction.

If you understand the basics but want to more deeply explore the how and why of Spring, Beginning Spring does a better job than most books I’ve read of conferring a genuine understanding of the framework in general use cases. Do keep in mind that the printed books listed here provide documentation of lower versions of Spring than 4.2. We have to wait for a positively-reviewed book that covers 4.2.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.