如何远程访问@Stateless@LocalBean



我正在关注一本来自packt的EJB食谱,其中包含以下代码:

package packt;
import javax.ejb.Stateless;
import javax.ejb.LocalBean;
//@Stateless
@LocalBean
@Stateless(mappedName="salutationBean")
public class Salutation {
    public String getFormalSalutation(String name) {
        return "Dear " + name;
    }
    public String getInformalSalutation(String name) {
        return "Hi " + name;
    }
}

如何从不扩展HttpServlet的类访问此bean?servlet本身运行良好:

package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import packt.Salutation;
@WebServlet(urlPatterns = {"/SalutationServlet"})
public class SalutationServlet extends HttpServlet {
    @EJB
    private Salutation salutation;
    protected void processRequest(HttpServletRequest request,
            HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet SalutationServlet</title>");
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>"
                    + salutation.getFormalSalutation("Sherlock Holmes")
                    + "</h1>");
            out.println("</body>");
            out.println("</html>");
        } finally {
            out.flush();
            out.close();
        }
    }
    @Override
    protected void doGet(HttpServletRequest request,
            HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request,
            HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
}

并且可以从指定的URL:中查看

thufir@dur:~$ 
thufir@dur:~$ lynx http://localhost:8080/SalutationApplication-war/SalutationServlet -dump
                              Dear Sherlock Holmes

thufir@dur:~$ 

目前的结构:

thufir@dur:~/NetBeansProjects$ 
thufir@dur:~/NetBeansProjects$ tree SalutationApplication/
SalutationApplication/
├── build.xml
├── nbproject
│   ├── ant-deploy.xml
│   ├── build-impl.xml
│   ├── genfiles.properties
│   ├── private
│   │   └── private.properties
│   ├── project.properties
│   └── project.xml
├── SalutationApplication-ejb
│   ├── build.xml
│   ├── nbproject
│   │   ├── ant-deploy.xml
│   │   ├── build-impl.xml
│   │   ├── genfiles.properties
│   │   ├── private
│   │   │   └── private.properties
│   │   ├── project.properties
│   │   └── project.xml
│   └── src
│       ├── conf
│       │   └── MANIFEST.MF
│       └── java
│           └── packt
│               └── Salutation.java
├── SalutationApplication-war
│   ├── build.xml
│   ├── nbproject
│   │   ├── ant-deploy.xml
│   │   ├── build-impl.xml
│   │   ├── genfiles.properties
│   │   ├── private
│   │   │   └── private.properties
│   │   ├── project.properties
│   │   └── project.xml
│   ├── src
│   │   ├── conf
│   │   │   └── MANIFEST.MF
│   │   └── java
│   │       └── servlet
│   │           └── SalutationServlet.java
│   └── web
│       ├── index.html
│       └── WEB-INF
└── src
    └── conf
        └── MANIFEST.MF
20 directories, 27 files
thufir@dur:~/NetBeansProjects$ 

现在,它只是一个本地bean是可以的,但最终我希望Salutation.java bean可以远程访问。我对Head First EJB中的EJB有一点熟悉,但这已经很老了。

(这个答案与我上面的评论有关。)

在容器不自动管理的对象中,可以通过获取对BeanManager的引用来初始化手动注入,并让CDI容器为您完成所有工作。这适用于也可以注入到托管bean中的所有内容,但不必进行复杂的JNDI查找。

public class CDIUtils {
    public static BeanManager beanManager() {
        try {
            return (BeanManager) new InitialContext().lookup("java:comp/BeanManager");
        } catch (NamingException e) {
            throw new IllegalStateException("Unable to obtain CDI BeanManager", e);
        }
    }
    public static void makeManagedStatic(Object obj) {
        BeanManager bm = beanManager();
        makeManaged(obj, bm);
    }
    public static void makeManaged(Object obj, BeanManager beanManager) {
        Class objClass = (Class) obj.getClass();
        AnnotatedType annotatedType = beanManager.createAnnotatedType(objClass);
        InjectionTarget injectionTarget = beanManager.createInjectionTarget(annotatedType);
        CreationalContext context = beanManager.createCreationalContext(null);
        injectionTarget.inject(obj, context);
    }
}

假设这是您的客户:

public class MyClient {
    @EJB private MyEJB myEJB;
    public void run() {
        if (myEJB == null)
            CDIUtils.makeManagedStatic(this);
        myEJB.someMethod();
    }
}

您也可以简单地在创建时对它们进行管理,这样就省去了null:的测试

MyClient client = new MyClient();
CDIUtils.makeManagedStatic(client);
client.run(); // etc

您可以创建一个接口并添加@Remote annotation:

@Remote
public interface MyRemoteInterface {
    void myRemoteMethod();    
}

之后,您可以在EJB中实现此接口:

@LocalBean
@Stateless(mappedName="salutationBean")
public class Salutation implements MyRemoteInterface {
    public String getFormalSalutation(String name) {
        return "Dear " + name;
    }
    public String getInformalSalutation(String name) {
        return "Hi " + name;
    }
    @Override
    public void myRemoteMethod(){
        // only this method will be visible in a remote interaction
    }
}

显然,你需要像一样将其注入客户端

@EJB
MyRemoteInterface remote;

提示:不要让远程客户端访问他们不需要的东西


编辑:取决于客户在哪里:

  • 如果您的客户端正在使用java组件(cdi对象、其他EJB、servlet、jaxr/jaxws工件),请使用@EJB(可能需要添加mappedName)
  • 如果客户端在ejb容器(即:独立的java应用程序)之外进行调用,则可以使用JNDI查找
  • 如果通过网络,您可以像web服务(@WebService/@Path)一样公开ejb并使用它……好吧,如果您喜欢的话

相关内容

  • 没有找到相关文章

最新更新