1. EJB3.0 Patterns
Asynchronous EJB3.0 Web Services on a Legacy
EJB with management interface
Michael Mountrakis mountrakis@uit.gr
Unified IT Services http:www.uit.gr
2. The problem
My company decided to migrate to EJB an old legacy
asynchronous application. The requirements are:
● Re – use legacy code from the application
● Define EJB3 design that :
● Employ Jboss Web Service calls to order jobs, gather
job resoults, cancel jobs.
● Employ a Jboss service to monitor the job processing
● Comply with EJB3.0 standards
Unified IT Services http:www.uit.gr
3. Comply with EJB3.0 standards
● Use J2EE annotations instead of XML
deployment descriptors
● Do not use threads
● Do not use I/O
● Benefit from EJB3.0 offered Jboss resources,
like Pojo Services, JMX platform....
Unified IT Services http:www.uit.gr
4. Design Synopsis
● Design a Web Service to offer clients the ability to:
to create requests, gather results, cancel requests.
● Design a Jboss Service that will process WS calls
and monitor the requests status.
● Design a Stateless EJB that will perform the
requests processing.
Unified IT Services http:www.uit.gr
5. Interfaces – Web Service
Clients can order Log Jobs, get Results and cancel
them:
@Remote
public interface LegacyProxyRemote {
// Order a long job asyncronously
int orderLongJobAsynch(String inData);
// Query String Results for this request using Id
String longJobResults( int jobId);
// Cancel this request
void longJobCancel( int jobId );
}
Unified IT Services http:www.uit.gr
6. Interfaces – JBoss Service Local
The Web Service passes the client's requests to
Jboss Service. This service has local interface:
@Local
public interface LegacyServiceLocal{
//WS asks Service to call the EJB for this job
int performLongJobAsynch(String inData);
//WS queries the Service for Job Results
String performLongJobResults(int jobId);
//WS cancels the job
void performLongJobCancel( int jobId);
//EJB performing the job resisters its thread to the
service
void registerThread( int jobId, long threadId);
}
Unified IT Services http:www.uit.gr
7. Interfaces – JBoss Service
Management
The service has also management:
@Management
public interface LegacyServiceManagement {
//JMX show the available job number
int currentJobs();
//JMX Show Only those non delivered to the W-S
String undeliveredJobs();
//JMX Show Active threads state of Threads
Executing the long jobs – carrying the EJB...
String threadsState();
//JMX Show – MBean Overriden cleanup
void stop();
}
Unified IT Services http:www.uit.gr
8. Interfaces – Stateless EJB
The service manages the Legacy EJB that performs
the job. This EJB has local interface as follows:
@Local
public interface LegacyEjbLocal {
//A long job that has String input and a String
output. This may calls JNI, Oracle, AS400....
String performLongJob(int jobid, String inData);
}
Unified IT Services http:www.uit.gr
10. Implementation: Web Service
● Web Service has a @EJB reference to the
service:
@Stateless
@Remote(LegacyProxyRemote.class)
@WebService
@SOAPBinding(style = Style.RPC)
public class LegacyProxyWS implements
LegacyProxyLocal, LegacyProxyRemote {
@EJB
LegacyServiceLocal service;
Unified IT Services http:www.uit.gr
11. Implementation Service
● The Jboss Service has a placeholder of all
asynchronous proxies to the EJB. The service
declaration is as follows:
@Service(objectName = LegacyService.OBJECT_NAME)
@Local(LegacyServiceLocal.class)
@Management(LegacyServiceManagement.class)
@LocalBinding(jndiBinding=LegacyService.JNDI_LOCAL)
public class LegacyService implements
LegacyServiceManagement,
LegacyServiceLocal {
Unified IT Services http:www.uit.gr
12. Implementation Service
● The service utilizes the Legacy Beans performing
asynhronous calls on them:
@Override
public synchronized int performLongJobAsynch(String inData) {
Integer key = generateKey();
LegacyEjbLocal synchEjb = (LegacyEjbLocal)
ctx.lookup(LegacyEjb.JNDI_LOCAL);
LegacyEjbLocal asynchrEjb = AsyncUtils.mixinAsync(synchEjb);
String ret = asynchrEjb.performLongJob(key, inData);
ejbStore.put(key, synchEjb, asynchrEjb);
return key;
}
The Asynchronous proxy
The Asynchronous call. Notice that „ret“ is always a NULL string
Unified IT Services http:www.uit.gr
13. Implementation Service
● Here is how results are collected:
@Override
public synchronized String performLongJobResults(int jobId) {
Integer key = new Integer(jobId);
LegacyEjbLocal asynchrEjb = ejbStore.getAsynch(key);
Future<String> future = (Future<String>) AsyncUtils
.getFutureResult(asynchrEjb);
if (future.isDone()) {
try {
ret = (String) future.get();
} catch (Exception e) {
e.printStackTrace();
}
Unified IT Services http:www.uit.gr
14. Implementation: Service
The service also monitors the thread state of
operating EJBs carrying out the Long Jobs:
@Override
public String threadsState() {
//Get a reference to Jboss Thread manager:
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
Set<Integer> set = ejbStore.keySet();
for (Integer i : set) {
long tid = ejbStore.getThreadId(i);
//Query the Jboss Thread manager for this thread id
ThreadInfo info = threadBean.getThreadInfo(tid);
if( info != null)
System.out.println(" thread state : "
+ info.getThreadState().toString() )
Unified IT Services http:www.uit.gr
15. Implementation: Legacy EJB
● The EJB performing the Long Job:
@Stateless
//@Stateful //can also be used...
@Local( LegacyEjbLocal.class )
@LocalBinding(jndiBinding=LegacyEjb.JNDI_LOCAL)
public class LegacyEjb implements LegacyEjbLocal{
@Resource
private SessionContext ctx;
…..
Unified IT Services http:www.uit.gr
16. Implementation: Legacy EJB
● The EJB informs Service Monitor about the
thread currently working on a request using a
Local Reference, aquired with JNDI:
public String performLongJob(int jobId, String inData) {
try {
LegacyServiceLocal service = (LegacyServiceLocal)
ctx.lookup(LegacyService.JNDI_LOCAL);
service.registerThread(jobId,
Thread.currentThread().getId() );
System.out.println("long job working...");
Thread.sleep(60 * 1000);
}
Unified IT Services http:www.uit.gr