Java EE6 Alternatives, A flexible configuration for enterprise applications

Another great feature of java ee 6 is the use of alternatives. The basic idea is to let you specify an alternative for an injected object. Take this case for example.
We are developing our front-end of our application. The screens depend on a database connection, but the database isn’t ready for development. We provide an ‘alternative’ implementation for this time being.
You can specify a mock and inject that. With this approach you need to change the wiring of your class.

public interface CustomerService {
    List findAllCustomers();
}

Your implementation would look something like this.

public class CustomerServiceImpl implements CustomerService {

    @PersistenceContext
    private EntityManager em;

    @Override
    public List findAllCustomers(){
        Query query = em.createNamedQuery("Customer.findAll", Customer.class);
        return query.getResultList();
    }
}

And the mock implementation like this.

public class CustomerServiceMock implements CustomerService {

    @Override
    public List findAllCustomers() {
        return Arrays.asList(new Customer("Geraldo"), new Customer("Scruffy"), new Customer("Haddock"));
    }

}

In your class that is using this service, you can just inject it.

@Inject private CustomerService customerService; 

When you try to run this, it will give an error:

‘Ambiguous dependencies for type [CustomerService] with qualifiers [@Default] at injection point [[field] @Inject private be.styledideas.blog.alternative.web.CustomerBackingBean.customerService]. Possible dependencies [[Managed Bean [class be.styledideas.blog.alternative.CustomerServiceMock] with qualifiers [@Any @Default], Managed Bean [class be.styledideas.blog.alternative.CustomerServiceImpl] with qualifiers [@Any @Default]]]. Please see server.log for more details.’

The container does not know what implementation should be injected. We will have to mark the mock implementation. We do this by adding the @Alternative annotation on top of it.

@Alternative
public class CustomerServiceMock implements CustomerService {

    @Override
    public List findAllCustomers() {
        return Arrays.asList(new Customer("Haddock"), new Customer("Geraldo"), new Customer("Scruffy"));
    }
}

When we now start our server, there is only one implementation that qualifies for this injection point, i.e. the CustomerServiceImpl class.
This isn’t what we want to achieve, we want to be able to inject our mock for the time we cannot connect to the database.
In our beans.xml file (CDI standard) we add this:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
    <alternatives>
        <class>be.styledideas.blog.alternative.CustomerServiceMock</class>
    </alternatives>
</beans>

Whenever we run our code, we will have a mock implementation where we use the customer service. Due this is configured in an xml file, we can change this without having to do a recompile of our application.
Next up, decorators.

8 thoughts on “Java EE6 Alternatives, A flexible configuration for enterprise applications”

  1. I’m not 100% sure that it’s a mistake, but you call the interface in some places CustomerService and in some others CustomerEntityService.

  2. “This isn’t what we want to achieve, we want to be able to inject our mock for the time we cannot connect to the database.”

    So how do exactly achieve this using @Alternative ?

    The code is slightly confusing as well as the interface name is “CustomerService” and the implementations are implementing “CustomerEntityService”. Similarly “CustomerEntityServiceMock” and “CustomerServiceMock”.

    1. The time we cannot connect to the database is a period that we want to overcome. For example while we are developing our front-end of our application. The screens depend on a database connection, but the database isn’t ready for development. We provide an ‘alternative’ implementation for this time being.
      So we have 2 implementations, so when we use CDI to inject this we get an error. The container does not know what to inject.
      By adding the @Alternative annotation, we mark one implementation as ‘alternative’. Meaning that the container now will choose the ‘primary’ implementation (the implementation that is not annotated with @Alternative).
      So if we want to use our ‘alternative’ implementation, we just have to specify it in the beans.xml file, so our container can inject the other one.
      I’ll update the post to make this part more clear.

  3. I don’t want to be pessimistic, but what happens when a user is accessing the production database (application is live), and application failed to connect to DB, would not it use the mock in this case?

    1. The mock will never be used when it is not specified in the beans.xml. The application failure must be handled in an other way.

  4. Pingback: JavaPins

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>