EntityManager injection works in JBoss 7.1.1 but not WebSphere 7
- by BikerJared
I've built an EJB that will manage my database access. I'm building a web app around it that uses Struts 2.
The problem I'm having is when I deploy the ear, the EntityManager doesn't get injected into my service class (and winds up null and results in NullPointerExceptions).
The weird thing is, it works on JBoss 7.1.1 but not on WebSphere 7.
You'll notice that Struts doesn't inject the EJB, so I've got some intercepter code that does that. My current working theory right now is that the WS7 container can't inject the EntityManager because of Struts for some unknown reason. My next step is to try Spring next, but I'd really like to get this to work if possible.
I've spent a few days searching and trying various things and haven't had any luck. I figured I'd give this a shot. Let me know if I can provide additional information.
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="JPATestPU" transaction-type="JTA">
<description>JPATest Persistence Unit</description>
<jta-data-source>jdbc/Test-DS</jta-data-source>
<class>org.jaredstevens.jpatest.db.entities.User</class>
<properties>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
package org.jaredstevens.jpatest.db.entities;
import java.io.Serializable;
import javax.persistence.*;
@Entity
@Table
public class User implements Serializable {
private static final long serialVersionUID = -2643583108587251245L;
private long id;
private String name;
private String email;
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@Column(nullable=false)
public String getName() {
return this.name;
}
public void setName( String name ) {
this.name = name;
}
@Column(nullable=false)
public String getEmail() {
return this.email;
}
@Column(nullable=false)
public void setEmail( String email ) {
this.email= email;
}
}
package org.jaredstevens.jpatest.db.services;
import java.util.List;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.Query;
import org.jaredstevens.jpatest.db.entities.User;
import org.jaredstevens.jpatest.db.interfaces.IUserService;
@Stateless(name="UserService",mappedName="UserService")
@Remote
public class UserService implements IUserService {
@PersistenceContext(unitName="JPATestPU",type=PersistenceContextType.TRANSACTION)
private EntityManager em;
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public User getUserById(long userId) {
User retVal = null;
if(userId > 0) {
retVal = (User)this.getEm().find(User.class, userId);
}
return retVal;
}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public List<User> getUsers() {
List<User> retVal = null;
String sql;
sql = "SELECT u FROM User u ORDER BY u.id ASC";
Query q = this.getEm().createQuery(sql);
retVal = (List<User>)q.getResultList();
return retVal;
}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void save(User user) {
this.getEm().persist(user);
}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public boolean remove(long userId) {
boolean retVal = false;
if(userId > 0) {
User user = null;
user = (User)this.getEm().find(User.class, userId);
if(user != null) this.getEm().remove(user);
if(this.getEm().find(User.class, userId) == null) retVal = true;
}
return retVal;
}
public EntityManager getEm() {
return em;
}
public void setEm(EntityManager em) {
this.em = em;
}
}
package org.jaredstevens.jpatest.actions.user;
import javax.ejb.EJB;
import org.jaredstevens.jpatest.db.entities.User;
import org.jaredstevens.jpatest.db.interfaces.IUserService;
import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport {
@EJB(mappedName="UserService")
private IUserService userService;
private static final long serialVersionUID = 1L;
private String userId;
private String name;
private String email;
private User user;
public String getUserById() {
String retVal = ActionSupport.SUCCESS;
this.setUser(userService.getUserById(Long.parseLong(this.userId)));
return retVal;
}
public String save() {
String retVal = ActionSupport.SUCCESS;
User user = new User();
if(this.getUserId() != null && Long.parseLong(this.getUserId()) > 0) user.setId(Long.parseLong(this.getUserId()));
user.setName(this.getName());
user.setEmail(this.getEmail());
userService.save(user);
this.setUser(user);
return retVal;
}
public String getUserId() {
return this.userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getName() {
return this.name;
}
public void setName( String name ) {
this.name = name;
}
public String getEmail() {
return this.email;
}
public void setEmail( String email ) {
this.email = email;
}
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user = user;
}
}
package org.jaredstevens.jpatest.utils;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class EJBAnnotationProcessorInterceptor implements Interceptor {
private static final long serialVersionUID = 1L;
public void destroy() {
}
public void init() {
}
public String intercept(ActionInvocation ai) throws Exception {
EJBAnnotationProcessor.process(ai.getAction());
return ai.invoke();
}
}
package org.jaredstevens.jpatest.utils;
import java.lang.reflect.Field;
import javax.ejb.EJB;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class EJBAnnotationProcessor {
public static void process(Object instance)throws Exception{
Field[] fields = instance.getClass().getDeclaredFields();
if(fields != null && fields.length > 0){
EJB ejb;
for(Field field : fields){
ejb = field.getAnnotation(EJB.class);
if(ejb != null){
field.setAccessible(true);
field.set(instance, EJBAnnotationProcessor.getEJB(ejb.mappedName()));
}
}
}
}
private static Object getEJB(String mappedName) {
Object retVal = null;
String path = "";
Context cxt = null;
String[] paths = {"cell/nodes/virgoNode01/servers/server1/","java:module/"};
for( int i=0; i < paths.length; ++i )
{
try {
path = paths[i]+mappedName;
cxt = new InitialContext();
retVal = cxt.lookup(path);
if(retVal != null) break;
} catch (NamingException e) {
retVal = null;
}
}
return retVal;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.devMode" value="true" />
<package name="basicstruts2" namespace="/diagnostics" extends="struts-default">
<interceptors>
<interceptor name="ejbAnnotationProcessor"
class="org.jaredstevens.jpatest.utils.EJBAnnotationProcessorInterceptor"/>
<interceptor-stack name="baseStack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="ejbAnnotationProcessor"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="baseStack"/>
</package>
<package name="restAPI" namespace="/conduit" extends="json-default">
<interceptors>
<interceptor name="ejbAnnotationProcessor"
class="org.jaredstevens.jpatest.utils.EJBAnnotationProcessorInterceptor" />
<interceptor-stack name="baseStack">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="ejbAnnotationProcessor" />
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="baseStack" />
<action name="UserAction.getUserById"
class="org.jaredstevens.jpatest.actions.user.UserAction" method="getUserById">
<result type="json">
<param name="ignoreHierarchy">false</param>
<param name="includeProperties">
^user\.id,
^user\.name,
^user\.email
</param>
</result>
<result name="error" type="json" />
</action>
<action name="UserAction.save"
class="org.jaredstevens.jpatest.actions.user.UserAction" method="save">
<result type="json">
<param name="ignoreHierarchy">false</param>
<param name="includeProperties">
^user\.id,
^user\.name,
^user\.email
</param>
</result>
<result name="error" type="json" />
</action>
</package>
</struts>
Stack Trace
java.lang.NullPointerException
org.jaredstevens.jpatest.actions.user.UserAction.save(UserAction.java:38)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
java.lang.reflect.Method.invoke(Method.java:611)
com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:453)
com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:292)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:255)
org.jaredstevens.jpatest.utils.EJBAnnotationProcessorInterceptor.intercept(EJBAnnotationProcessorInterceptor.java:21)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:256)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:176)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265)
org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:68)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:211)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:211)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:190)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:75)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:90)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:243)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:176)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:192)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:187)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54)
org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:511)
org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)
com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:188)
com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:116)
com.ibm.ws.webcontainer.filter.WebAppFilterChain._doFilter(WebAppFilterChain.java:77)
com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:908)
com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:997)
com.ibm.ws.webcontainer.extension.DefaultExtensionProcessor.invokeFilters(DefaultExtensionProcessor.java:1062)
com.ibm.ws.webcontainer.extension.DefaultExtensionProcessor.handleRequest(DefaultExtensionProcessor.java:982)
com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3935)
com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:276)
com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:931)
com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1583)
com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:186)
com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:452)
com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:511)
com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:305)
com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:276)
com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.sendToDiscriminators(NewConnectionInitialReadCallback.java:214)
com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.complete(NewConnectionInitialReadCallback.java:113)
com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)
com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)
com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)
com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1604)