Platinum Partner
java

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.

 

From http://styledideas.be/blog/2011/06/07/java-ee6-alternatives-a-flexible-configuration-for-enterprise-applications/

{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}