0

データベースアクセスを管理するEJBを作成しました。Struts2を使用するWebアプリを構築しています。

私が抱えている問題は、earをデプロイするときに、EntityManagerがサービスクラスに注入されないことです(そしてnullになり、NullPointerExceptionsが発生します)。

奇妙なことに、JBoss 7.1.1では動作しますが、WebSphere7では動作しません。

StrutsがEJBを挿入しないことに気付くでしょう。そのため、それを実行するインターセプターコードがいくつかあります。私の現在の作業理論は、何らかの理由でStrutsが原因で、WS7コンテナーが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)
4

2 に答える 2

2

ここでの本当の問題は、EJB が注入していないことでした。インターセプタ コードが JNDI で EJB を正常にルックアップできず、EJB へのローカル参照を null に設定していました。これが修正されると、EntityManager が注入され、すべてが再び満足のいくものになります。

これに対する解決策は次の 2 つでした。

  1. インターセプター クラスの JNDI ルックアップが失敗していました。これは、ハードコーディングしたパスが使用中のサーバーに対して間違っていたためです。
  2. WS7 構成では、インターセプター クラスが正しい EJB を検出できるように、アプリケーションの EJB 設定にエイリアスが必要でした。

#1 を修正するには、コードを修正しました。サーバーに依存しませんが、これにはより良い解決策が必要です。

#2 を修正するには:

  1. コンソールにログインします。(http://サーバー名:9080/admin)
  2. アプリケーション -> アプリケーション タイプ -> Websphere エンタープライズ アプリケーション。
  3. アプリケーション名 (私の場合は JPATestEAR) をクリックします。
  4. 右側にリンクがあります。[EJB JNDI 名] をクリックします (すべての EJB が一覧表示されます)。
  5. 右側には、各 EJB のエイリアスを入力できるラジオ ボタンとフォーム フィールドがあります。「すべてのインターフェースの JNDI 名」を使用し、「UserService」フィールドに EJB 名を入力しました。
  6. [保存] をクリックして、設定を再度保存します。

私を正しい軌道に乗せてくれてありがとう@bkail。

于 2012-11-03T20:28:40.073 に答える
0

アプリケーションが WAR としてパッケージ化されている場合、これが WS7 で動作しない理由を説明している可能性があります。

bkail が指摘したように、パッケージの問題である可能性があります。

EE6 以降、war アプリケーションの一部としてローカル EJB Bean をバンドルできますが、EE6 以前では、これを ear としてデプロイし、ejb を ejb-jar にパックする必要があります。

Websphere 8+ を試すと、おそらく動作するか、ejb-jar モジュールと war モジュールを使用してアプリケーションを ear として再パッケージ化できるはずです。

于 2012-11-03T16:57:35.503 に答える