是否可以创建一个接受回调并在其上调用它的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实现。
答案 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
才能使示例正常工作。