Introduction

This example shows how to write a Java job which calls a Session EJB.

Feature Status

FEATURE AVAILABILITY STARTING FROM RELEASE 1.3 FEATURE AVAILABILITY ENDING WITH RELEASE 1.10

JS-1314 - Getting issue details... STATUS

Downloads

Instructions

  • Deploy the ConverterBean from Chapter 24 of the sun j2ee tutorial at http://java.sun.com/j2ee/1.4/docs/tutorial/doc/ onto your j2ee server.
  • Get the application client from Chapter 24 of the tutorial running. Don't even try to do the rest of this HowTo if you don't get the application client running. This HowTo is not about setting up EJBs on a j2ee server. It is not about connecting EJB clients to the server. It is about writing Java Jobs for the JobScheduler which act as an EJB client. It will tell you how to configure the JobScheduler in order to find all required libraries and get the jndi lookup right.
  • Unzip all files from ejb.zip into the ./config/live folder of your JobScheduler installation.
  • Create a new foler ejb in the lib directory of your JobScheduler installation.
  • Put EJBJob.jar and all the jars which are needed to run the application client (this may depend on the application server you are using) into the lib/ejb directory.
  • If you need to set jndi properties, write a jndi.properties file and put it into the lib/ejb directory.
  • Edit config/factory.ini
  • Look for the class_path entry and add ;${SCHEDULER_HOME}/lib/ejb/*.jar;${SCHEDULER_HOME}/lib/ejb. (The second entry is required to find the jndi.properties file.) On Linux and Unix systems, use ":" as separator instead of ";".
  • Restart the JobScheduler
  • Open the web interface of the JobScheduler in your browser using http://scheduler_host:scheduler_port
  • Open the JOB CHAINS tab and enable "Show orders".
  • Find the job chain samples/ejb/ejb_chain.
  • Find the order my_order, open the order menu and choose "Show log".

A window will open showing the log of the order. As the order isn't running yet, the window will show nothing more than a line indicating the next start time of this order. Leave the window open and move it to a place where you can see it along with the main browser window.

  • Start the order by choosing "Start order now" from the Order menu.
  • Watch the log grow in the other window

The order will run through both steps of the job chain. In the first step, the EJB will be called. The second step will log the order parameters, which now include values for Euro an Yen which have been calculated by the EJB in the first step.

How it works

The Job Chain ejb_chain consists of two steps. In the first step, the job ejb is called. The implementation of the job will be explained below. In the second step, the readparam job is called. The readparam job is a small javascript job which reads all order parameters and logs them on info-level.

The order my_order is configured with one order parameter dollar which is set to "210". The job ejb reads this order parameter and calls the EJB to convert the dollars to Euro and Yen. It then sets two new order parameters (euro and yen) holding the converted currencies. (Please note that the bean doesn't use realtime rates. The rates are hard-coded into the bean. To make things worse, the application client from the j2ee tutorial had a bug: it used the yenToEuro() function to convert Dollars into Euro, resulting in a very small Euro value. We've fixed this bug for our example job.)

The Job Implementation is a subclass of sos.spooler.Job_impl (like all java JobScheduler jobs). It overrides the spooler_init() and spooler_exit() methods. In spooler_init(), the job connects to the naming service (lines 25 and 26) and then resolves and creates the EJB (lines 27-33).

spooler_init() is called when a task for the job is created. spooler_process() is called for every order which is processed by the job. So if you try out the example multiple times by adding other orders or by restarting my_order, the bean will only be created once but there will be multiple calls to spooler_process. Have a look at the job definition ejb.job.xml. It has an attribute idle_timeout="600". This means that a task for this job may run idle for 600 seconds, until the JobScheduler will end the task. So if you wait 600 seconds (10 min) before starting the next order, the task will end and the reference to the EJB will be lost (as the whole jvm is terminated). When the next order is processed, a new task has to be created, thus spooler_init() will be called again.

If everything went fine, spooler_init() will return true (line 35), which means "Initialization was OK, I am now ready to process orders". If an error occured, it will be logged and spooler_init() will return false (line 39). This means "Initialization went wrong, I will not process orders". The job will go into the stopped state and orders will remain enqueued. If the job is unstopped, it will again try to initialized and process the enqueued orders. You can give it a try by undeploying your ejb and then starting the order.

In spooler_process the order parameter dollar is read (lines 48-54). If it exists, it is used as the input parameter for the dollarToYen() call. The EJB is then called (lines 57 and 61) and the results are written as new order parameters (lines 58 and 62).

If everything worked, spooler_process will return true, which means "the order may proceed to the state configured as next_state" (which is show_params in this job chain). If an error occured, spooler_process will return false, which causes the order to go to the error_state (or to take different actions depending on the on_error attribute of the job chain node. see http://www.sos-berlin.com/doc/en/scheduler.doc/xml/job.xml#attribute_stop_on_error).

Source Code of EJBJob.java

01: import java.math.BigDecimal; 
02: 
03: import javax.naming.Context; 
04: import javax.naming.InitialContext; 
05: import javax.rmi.PortableRemoteObject; 
06: 
07: import converter.Converter; 
08: import converter.ConverterHome; 
09: import sos.spooler.Job_impl; 
10: import sos.spooler.Order; 
11: import sos.spooler.Variable_set; 
12: 
13: public class EJBJob extends Job_impl { 
14: 
15:     private Converter currencyConverter; 
16: 
17: 
18:     /*  
19:      * spooler_init() is called when a task is created 
20:      */ 
21:     public boolean spooler_init() throws Exception { 
22:         try { 
23:             spooler_log.debug1("Creating initial context..."); 
24: 
25:             Context initial = new InitialContext(); 
26:             Context myEnv = (Context) initial.lookup("java:comp/env"); 
27:             Object objref = myEnv.lookup("ejb/SimpleConverter"); 
28: 
29:             ConverterHome home = 
30:                 (ConverterHome) PortableRemoteObject.narrow(objref, 
31:                 ConverterHome.class); 
32: 
33:             currencyConverter = home.create(); 
34:             spooler_log.debug1("EJB created."); 
35:             return true; 
36:         } catch (Exception e){ 
37:             spooler_log.error("An error occured connecting to the EJB: "+e); 
38:         } 
39:         return false; 
40:     } 
41: 
42:     /*  
43:       * spooler_process() is called for every order which is processed 
44:       * by the task. 
45:       */ 
46:     public boolean spooler_process() throws Exception { 
47:         try { 
48:             Order order = spooler_task.order(); 
49:             Variable_set orderParams = order.params(); 
50: 
51:             BigDecimal param = new BigDecimal("100.00"); 
52:             if (orderParams.value("dollar").length()>0){ 
53:                 param = new BigDecimal(orderParams.value("dollar")); 
54:             } 
55:             spooler_log.info("Calling EJB"); 
56:             spooler_log.debug1("Dollar: "+param); 57: BigDecimal amount = currencyConverter.dollarToYen(param); 
58:             orderParams.set_var("yen", amount.toString()); 
59:             spooler_log.debug1("Yen: "+amount); 
60: 
61:             amount = currencyConverter.yenToEuro(param); 
62:             orderParams.set_var("Euro", amount.toString()); 
63:             spooler_log.debug1("Euro: "+amount); 
64: 
65:             return true; 
66:         } catch (Exception ex) { 
67:             spooler_log.error("Caught an unexpected exception: "+ex); 
68:         } 
69:         return false; 
70:     } 
71: 
72: }

See also

  • No labels