Reputation: 4160
Currently we have a deployment architecture were a bunch of data oriented services are exposed via RMI to business services. Both types (the data oriented services and the business services) are stateless session beans. Each data-service interface package (containing the remote interfaces) also has a locator, that does the JNDI lookup. We so this so that we can call an data oriented service from anywhere in the business service logic.
This is how a locator looks like:
public final class OMRLocator {
private static final Logger LOG = Logger.getLogger( OMRLocator.class );
private static final String ORG_WILDFLY_INITIAL_CTX_FACTORY = "org.wildfly.naming.client.WildFlyInitialContextFactory";
private OMRLocator() {
}
@Produces
public static OrganisationsAndMandatesRegister locate() {
try {
Properties ctxProp = new Properties();
ctxProp.put( Context.INITIAL_CONTEXT_FACTORY, ORG_WILDFLY_INITIAL_CTX_FACTORY );
InitialContext ctx = new InitialContext( ctxProp );
return (OrganisationsAndMandatesRegister) ctx.lookup( OrganisationsAndMandatesConstants.REMOTE_NAME );
}
catch ( NamingException ex ) {
LOG.log( Level.WARN, "Cannot reach: " + OrganisationsAndMandatesConstants.REMOTE_NAME, ex );
return null;
}
}
}
We were running on JBOSS EAP6 and started to experiment with CDI. Hence, we added a beans.xml
to the data-service-beans and the @Produces
to make the (in this case OrganisationAndMandatesRegister
CDI injectable. The idea is that the future we might repackage our application and package the data-services together with the business-service in one enterprise archive.
Lately we migrated to JBOSS EAP7.2 (Wildfly 8?) and suddenly we see all kinds of unexpected latency and transaction problems.
My suspicion is that the way we obtain beans are a factor in these problems. For instance: I guess the scope is dependent on the business EJB lifecycle, but for each call to the locate()
in the business service a new instance of a data-service is produced.
So: what is the best way to produce a remote bean (via RMI) when using CDI? Should I take scoping into consideration given that both types of services are stateless (or is this done automatically)?
Upvotes: 3
Views: 1422
Reputation: 506
If no scope is defined on the producer method then @Dependend is used, so find the proper scope, maybe @RequestScoped. When you retrieve an EJB from JNDI you do not get a new instace, you get an instance from the pool which could be the same over multiple calls. Your problem could be the EJB interceptors because if dependent scoped the EJB instance is always the same once injected an is never released.
Get rid of the @Produces because CDI integrates with EJB and EJBs can be injected via @Inject or @EJB. If you want to keep the Locator class then you can inject the EJBs in there and return the proper EJB instance (which is actually a proxy), whereby the Locator should be @ApplicationScoped. Another way is to to use Instance which alows a programmatic lookup. With the type Object you can access all CDI Beans (including EJBs) of the container so a common interface would be useful to minimize accessible beans.
See the following links for more help.
http://www.adam-bien.com/roller/abien/entry/inject_vs_ejb
Just to summarise:
option a) Leave as is. Perhaps make scope explicit with @Dependent
to indicate this is called at calling-bean-creation (injecting in constructor of calling bean)
option b) Use a stateless @ApplicationScoped
session bean
@LocalBean // otherwise @EJB will not work
@ApplicationScoped // this instance should be created only once per ear
public class OMRLocator {
@EJB // does implicitly a remote (default) JNDI lookup
private OrganisationsAndMandatesRegister instance;
@Produces
@Dependent // just to make it explicit
public OrganisationsAndMandatesRegister locate() {
return instance;
}
}
Upvotes: 4