我已经构建了一个EJB来管理我的数据库访问。我正在构建一个使用Struts 2的Web应用程序。
我遇到的问题是当我部署耳朵时,EntityManager不会被注入我的服务类(并且会结束null并导致NullPointerExceptions)。
奇怪的是,它适用于JBoss 7.1.1,但不适用于WebSphere 7。
你会注意到Struts没有注入EJB,所以我有一些内部代码可以做到这一点。我现在的工作原理是WS7容器由于某些未知原因而不能因为Struts而注入EntityManager。我的下一步是接下来尝试Spring,但如果可能的话,我真的想让它工作。
我花了几天时间搜索和尝试各种各样的事情并没有任何运气。我想我会试一试。如果我能提供更多信息,请告诉我。
<?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>
堆栈跟踪
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)
答案 0 :(得分:2)
这里真正的问题是EJB没有注入。我的拦截器代码无法在JNDI中成功查找EJB,并将我对它的本地引用设置为null。修复后,EntityManager会被注入,一切都很快乐。
对此的解决方案有两方面:
修复#1 - 我修改了我的代码。我需要一个更好的解决方案,尽管这与服务器无关。
修复#2:
感谢@bkail让我走上正轨。
答案 1 :(得分:0)
如果你的应用程序是包作为WAR,这可以解释为什么它不适用于WS7。
正如bkail所指出的,它可能是包装问题。
从EE6开始,您可以将本地EJB bean捆绑为war应用程序的一部分,但在EE6之前,您需要将其部署为ear并将ejb打包在ejb-jar中。
您可以尝试使用Websphere 8+,它应该可以使用ejb-jar模块和ekb-jar模块工作或重新打包您的应用程序。战争模块。