
We always hear about the Spring vs Java EE fight. Do we always have to use one of them? For sure, they give you a lot of facilities, but, do we need all of those features that they bring with them every time? Well, actually you don't need to choose one of them always. There are a lot of other alternatives that help you build your applications, so, why not take a look at few of them?
I'm here to show an alternative called Apache DeltaSpike. Apache DeltaSpike is a set of CDI extensions that brings a lot of useful features. This post will show you five great features of this tool.
Before continuing, be aware that if you want to use any module, obligatorily you need to add the core module as a dependency.
def deltaSpikeVersion = 'last-version-here'
compile group: 'org.apache.deltaspike.core', name:'deltaspike-core-api', version: deltaSpikeVersion
compile group: 'org.apache.deltaspike.core', name:'deltaspike-core-impl', version: deltaSpikeVersion
The Transactional Interceptor
As we know, CDI beans are not transactional. This is what most people miss when they are using CDI beans outside a Java EE container, because this time they cannot use EJBs to handle these transactions. DeltaSpike gives you a simple interceptor which handle transactions for you.
How to use it
First of all, you need to add the DeltaSpike's JPA dependency to your application.
compile group: 'org.apache.deltaspike.modules', name:'deltaspike-jpa-module-api', version: deltaSpikeVersion
compile group: 'org.apache.deltaspike.modules', name:'deltaspike-jpa-module-impl', version: deltaSpikeVersion
Also, you need to enable the interceptor. (No needed if you are using CDI 1.1+ and DeltaSpike 1.1.1+)
<beans>
<interceptors>
<class>org.apache.deltaspike.jpa.impl.transaction.TransactionalInterceptor</class>
</interceptors>
</beans>
And then you need to produce your EntityManager.
public class JPAProducer {
@Produces
@Default
@RequestScoped
public EntityManager entityManager(EntityManagerFactory entityManagerFactory) {
return entityManagerFactory.createEntityManager();
}
public void close(@Disposes @Any EntityManager entityManager) {
if (entityManager.isOpen()) {
entityManager.close();
}
}
}
Now, if you want to make a method transactional, you need to do as the code below:
public class AddressService {
@Inject
private AddressRepository addressRepository;
@Transactional
public void save(Address address) {
addressRepository.save(address);
}
public Address fetch(Long id){
return addressRepository.findBy(id);
}
}
You also can annotate the class, thus, all the methods will be transactional.
The Data module
As much as you love Java EE, you should admit: SpringData is awesome! No need to write repositories implementations, you only need to declare your methods in the JPA repository interface properly.
What if I told you that you can also use a feature like SpringData without Spring? The Apache DeltaSpike offers this feature as a module, and it is as easy as pie!
How to use it
As the JPA module, you need to add the Data module to your application dependencies.
compile group: 'org.apache.deltaspike.modules', name:'deltaspike-data-module-api', version: deltaSpikeVersion
compile group: 'org.apache.deltaspike.modules', name:'deltaspike-data-module-impl', version: deltaSpikeVersion
Then you can create your repository:
@Repository
public interface AddressRepository extends EntityRepository<Address, Long>{
@Query("FROM Address a where a.streetName = ?1")
Address findByStreet(String streetName);
}
And, if you want to use it:
@Inject
private AddressRepository addressRepository;
Scheduling things
DeltaSpike also allows you to create Quartz based services, so, you are able to schedule batch processes.
How to use it
To do so, first you need to add the scheduler module to your application.
compile group: 'org.apache.deltaspike.modules', name:'deltaspike-scheduler-module-api', version: deltaSpikeVersion
compile group: 'org.apache.deltaspike.modules', name:'deltaspike-scheduler-module-impl', version: deltaSpikeVersion
And to use it, just:
@Scheduled(cronExpression = "0 0/5 * * * ?")
public class MyJob implements Job { //org.quartz.Job
@Inject //you can inject any bean you want
private MyService service;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException{
//do batch things here
}
}
The Partial Bean Binding feature
This is a very useful (although not very common) feature. You can actually create dynamic implementations at runtime with it! This is just how the Data module works: you just add the annotations to an interface and a partial bean binding does all the work behind the scenes.
How to use it
If you want to use it, you need to use use the partial bean binding dependency in your application.
compile group: 'org.apache.deltaspike.modules', name:'deltaspike-partial-bean-module-api', version: deltaSpikeVersion
compile group: 'org.apache.deltaspike.modules', name:'deltaspike-partial-bean-module-impl', version: deltaSpikeVersion
Then, you create an annotation and annotate it with the @PartialBeanBinding annotation.
@PartialBeanBinding
@Retention(RUNTIME)
@Target(TYPE)
public @interface MyAnnotation {
}
After that, you need to create an Invocation Handler
@MyAnnotation
public class MyInvocationHandler implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//handle all the method invocations here
}
}
For sure it opens your mind for you to do a lot of things! For example, you could implement a feature just like the SpringData MongoDB, considering that DeltaSpike Data only allows you to work with JPA entities. Just saying. ;)
Testing
You can also test your CDI application easily with DeltaSpike, through the Test-Control module. It gives you the control to start and stop CDI contexts and works with both Weld and OpenWebBeans implementations.
How to use it
As any other DeltaSpike module, you need to add it apart the core module:
testCompile group: 'org.apache.deltaspike.modules', name:'deltaspike-test-control-module-api', version: deltaSpikeVersion
testCompile group: 'org.apache.deltaspike.modules', name:'deltaspike-test-control-module-impl', version: deltaSpikeVersion
//If you are using OpenWebBeans as CDI provider
testCompile group: 'org.apache.deltaspike.cdictrl', name:'deltaspike-cdictrl-owb', version: deltaSpikeVersion
testCompile group: 'org.apache.openwebbeans', name:'openwebbeans-impl', version: owbVersion
//If you are using Weld as CDI provider
testCompile group: 'org.apache.deltaspike.cdictrl', name:'deltaspike-cdictrl-weld', version: deltaSpikeVersion
testCompile group: 'org.jboss.weld.se', name:'weld-se-core', version: weldSeVersion
After that, you need just to use the CdiTestRunner runner and you will be able to inject CDI beans into your test class.
@RunWith(CdiTestRunner.class)
public class MyCdiBeanTest{
@Inject
private MyCdiBean myCdiBean;
@Test
//JUnit tests over here
}
You can also work with mocks through the DynamicMockManager. You can check it out over here.
Finalizing...
As you could see, DeltaSpike is a great tool. It allows you to do a lot of things in very a simple way. DeltaSpike is already a mature tool, so, you can use it as you please. You can read more about DeltaSpike at http://deltaspike.apache.org/.
I hope this post was helpful to you. Any questions, please leave a comment.
[]'s