是否可以为EJB服务调用一个回调

时间:2016-08-30 15:14:32

标签: java java-ee ejb

是否可以创建一个接受回调并在其上调用它的EJB服务 调用服务的客户端?用例是:上传大字节数组 将解析它并将结果转换为对象和服务的服务 坚持他们。我想通知客户端哪些步骤已经完成。

@Local
public interface MyService {
    Status upload(byte[] content, Callable<Void> onReceived, Calable<Void> onPersisting);
}

@Stateless(name = "MyService")
public class MyServiceImpl extends MyService {
    Status upload(byte[] content, Callable<Void> onReceived, Calable<Void> onPersisting) {
        // Invoke this because all date is transfered to server.
        onReceived.call();
        // Do the parsing stuff ...
        onPersisting.call();
        // Do the persisting stuff ...
        return new Status(...); // Done or failed or such.
    }
}

在客户端我传入callables:

Context ctx = ...
MyService service = ctx.get(...);

ctx.upload(bytes, new Callable<void() {
    @Override
    public Void call() {
        // Do something
        return null;
    }
}, new Callable<Void>() {
    @Override
    public Void call() {
        // Do something
        return null;
    }
});

EJB中是否可以这样?

我是JEE世界的新手:我知道客户端获得了EJB的一些存根 接口和呼叫由&#34;背景魔法转移&#34;到服务器 真正的EJB实现。

1 个答案:

答案 0 :(得分:1)

案例1:使用本地业务接口(或无接口视图)

是的,只要您的服务仅由本地业务接口访问即可。为什么?本地业务接口只能由本地客户端访问。

  

本地客户端具有以下特征[LocalClients]

     
      
  • 它必须在与其访问的企业bean相同的应用程序中运行。

  •   
  • 它可以是Web组件或其他企业bean。

  •   
  • 对于本地客户端,它访问的企业bean的位置不透明。

  •   

总结重要特征。它分别在同一个应用程序JVM中运行,它是一个Web或EJB组件,并且访问的bean的位置对于本地客户端是不透明的。有关详细信息,请查看LocalClients

下面是一个简单的 Hello World 示例。我的示例使用无接口视图,这相当于本地业务接口。

编辑:通过JNDI查找扩展的示例。

/** Service class */

import javax.ejb.Stateless;

@Stateless
public class Service {

    public void upload(final Callback callback) {
        callback.call();
    }

}

/** Callback class */

public class Callback {

    public void call() {
        System.out.println(this + " called.");
    }

}

/** Trigger class */

import javax.ejb.EJB;
import javax.ejb.Schedule;
import javax.ejb.Singleton;

@Singleton
public class Trigger {

    @EJB
    Service service;

    @Schedule(second = "*/5", minute = "*", hour = "*", persistent = false)
    public void triggerService() {
        System.out.println("Trigger Service call");
        service.upload(new Callback());
        //or by JNDI lookup and method overriding
        try {
           Service serviceByLookup = (Service) InitialContext.doLookup("java:module/Service");
           serviceByLookup.upload(new Callback() {
               @Override
               public void call() {
                   System.out.println("Overriden: " + super.toString());
               }
           });

       } catch (final NamingException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       }
    }
}

也可以将Callback类实现为StatelessBean并将其注入Service类。

/** Service class */
@Stateless
public class Service {

    @EJB
    Callback callback;

    public void upload() {
        callback.call();
    }

}

案例2:使用远程业务接口

如果使用远程接口,则无法将回调对象传递给EJB。要将状态信息返回给客户端,您必须使用JMS。

以下简短的启动示例。

@Remote
public interface IService {

    void upload();

}

@Stateless
public class Service implements IService {

    @EJB
    private AsyncUploadStateSender uploadStateSender;

    @Override
    public void upload() {
        for (int i = 0; i <= 100; i += 10) {
            uploadStateSender.sendState(i);
            try {
                Thread.sleep(1000L);
            } catch (final InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


@Stateless
public class AsyncUploadStateSender {

    @Resource(lookup = "jms/myQueue")
    private Queue queue;

    @Inject
    private JMSContext jmsContext;

    @Asynchronous
    public void sendState(final int state) {
        final JMSProducer producer = jmsContext.createProducer();
        final TextMessage msg = jmsContext.createTextMessage("STATE CHANGED " + state + "%");
        producer.send(queue, msg);
    }
}

public class Client {

    public static void main(final String args[]) throws NamingException, InterruptedException, JMSException {

        final InitialContext ctx = ... // create the InitialContext;
        final IService service = (IService) ctx.lookup("<JNDI NAME OF IService>");
        final ConnectionFactory factory = (ConnectionFactory) ctx.lookup("jms/__defaultConnectionFactory");
        final Queue queue = (Queue) ctx.lookup("jms/myQueue");
        // set consumer
        final Connection connection = factory.createConnection();
        final MessageConsumer consumer = connection.createSession().createConsumer(queue);
        consumer.setMessageListener(new MessageListener() {
            @Override
            public void onMessage(final Message msg) {
                try {
                    System.out.println(((TextMessage) msg).getText());
                } catch (final JMSException e) {
                    e.printStackTrace();
                }
            }
        });
        connection.start();
        // start upload
        service.upload();
        Thread.sleep(1000L);
    }
}

注意:您必须在应用程序服务器中创建队列jms/myQueue和连接工厂jms/__defaultConnectionFactory才能使示例正常工作。