如何远程访问@Stateless @LocalBean

时间:2014-09-06 12:35:46

标签: java java-ee netbeans ejb ejb-3.1

我正在使用以下代码关注来自packt的EJB cookbook

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);
    }
}

可从指定的网址查看:

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,但这已经很老了。

2 个答案:

答案 0 :(得分:2)

您可以创建一个界面并添加@Remote注释:

@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,jaxrs / jaxws工件),请使用@EJB(可能需要添加mappedName)
  • 如果客户端在ejb容器外部调用(即:独立的Java应用程序),则可以使用JNDI查找
  • 如果是通过网络,您可以将您的ejb公开为Web服务(@ WebService / @ Path)并使用它...好吧,如果您喜欢它。

答案 1 :(得分:2)

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

在容器不自动管理的对象中,您可以通过获取对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