websphere-8workload-schedulertivoli-work-scheduler

How to call EJB from another app on the same server?


I have java SE sample client which run on desktop (code below). But I have access to WebSphere were called EJB is deployed. How to rewrite below code to work on WebSphere? (When I leave this code just like it is program works but I think this can be done more simple and clear)

Main method:

WSConn connection = new WSConn();
final Plan plan = connection.getPlanBean();
com.ibm.websphere.security.auth.WSSubject.doAs(connection.getSubject(), new java.security.PrivilegedAction<Object>() {
public Object run() {
try {
    // App logic
} catch (Throwable t) {
    System.err.println("PrivilegedAction - Error calling EJB: " + t);
t.printStackTrace();
   }
     return null;
  }
}); // end doAs

WSConn class:

public class WSConn {
    private static final String INITIAL_CONTEXT_FACTORY = "com.ibm.websphere.naming.WsnInitialContextFactory";
    private static final String JAAS_MODULE = "WSLogin";
    private static final String MODEL_EJB_NAME_LONG = "ejb/com/ibm/ModelHome";
    private static final String PLAN_EJB_NAME_LONG = "ejb/com/ibm/PlanHome";
    private Subject subject;
    private InitialContext initialContext;
    private String serverName;
    private String serverPort;
    private String uid;
    private String pwd;
    private String remoteServerName;
    private Model modelBean;
    private Plan planBean;
    public WSConn() {
        Properties props = new Properties();
        try {
            props.load(WSConn.class.getClassLoader().getResourceAsStream("WSConn.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        serverName = props.getProperty("WSConn.serverName");
        serverPort = props.getProperty("WSConn.serverPort");
        uid = props.getProperty("WSConn.userID");
        pwd = props.getProperty("WSConn.password");
        remoteServerName = props.getProperty("WSConn.remoteServerName");
    }

    private void init() {
        if (subject == null || initialContext == null) {
            subject = login();
        }
    }

    private Subject login() {

        Subject subject = null;
        try {
            LoginContext lc = null;

            // CRATE LOGIN CONTEXT
            Hashtable<String, String> env = new Hashtable<String, String>();
            env.put(Context.INITIAL_CONTEXT_FACTORY, INITIAL_CONTEXT_FACTORY);
            env.put(Context.PROVIDER_URL, "corbaloc:iiop:" + serverName + ":" + serverPort);

            initialContext = new InitialContext(env);

            // Just to test the connection
            initialContext.lookup("");

            lc = new LoginContext(JAAS_MODULE, new WSCallbackHandlerImpl(uid, pwd));
            lc.login();

            subject = lc.getSubject();


        } catch (javax.naming.NoPermissionException exc) {
            System.err.println("[WSConn] - Login Error: " + exc);

        } catch (Exception exc) {
            System.err.println("[WSConn] - Error: " + exc);
        }
        return subject;
    }

    public wModel getModelBean() {
        if (modelBean == null) {
            init();
            modelBean = (wModel) com.ibm.websphere.security.auth.WSSubject.doAs(subject,
                    new java.security.PrivilegedAction<wModel>() {
                        public wModel run() {
                            wModel session = null;
                            try {
                                Object o = initialContext.lookup(MODEL_EJB_NAME_LONG);
                                wModelHome home = (wModelHome) PortableRemoteObject.narrow(o, wModelHome.class);

                                if (home != null) {
                                    session = home.create(remoteServerName);
                                }

                            } catch (Exception exc) {
                                System.err.println("Error getting model bean: " + exc);
                            }
                            return session;
                        }
                    }); // end doAs
        }

        return modelBean;
    }

    public wPlan getPlanBean() {
        if (planBean == null) {
            init();
            planBean = (wPlan) com.ibm.websphere.security.auth.WSSubject.doAs(subject,
                    new java.security.PrivilegedAction<wPlan>() {
                        public wPlan run() {
                            wPlan session = null;
                            try {
                                Object o = initialContext.lookup(PLAN_EJB_NAME_LONG);
                                wPlanHome home = (wPlanHome) PortableRemoteObject.narrow(o, wPlanHome.class);

                                if (home != null) {
                                    session = home.create(remoteServerName);
                                }

                            } catch (Exception exc) {
                                System.err.println("Error getting plan bean: " + exc);
                            }
                            return session;
                        }
                    }); // end doAs
        }

        return planBean;
    }

    public Subject getSubject() {
        if (subject == null) {
            init();
        }

        return subject;
    }
}

Solution

  • As indicated in another answer, the classic mechanism is to lookup and narrow the home interface.

    Get the initial context

    final InitialContext initialContext = new InitialContext();
    

    Lookup for the home by jndi name, specifying either the full jndi name

    Object obj = initialContext.lookup("ejb/com/ibm/tws/conn/plan/ConnPlanHome");
    

    or you can create e reference in your WAR and use java:comp/env/yourname

    Then narrow the home to the home interface class

    ConnPlanHome planHome = (ConnPlanHome)PortableRemoteObject.narrow(obj, ConnPlanHome.class);
    

    and then create the EJB remote interface

    ConnPlan plan = planHome.create();
    

    The about calls should work for IBM Workload Scheduler distributed. For IBM Workload Scheduler z/OS the JNDI name and the class names are different:

    final InitialContext initialContext = new InitialContext();
    String engineName = "XXXX";
    Object obj = initialContext.lookup("ejb/com/ibm/tws/zconn/plan/ZConnPlanHome");
    ZConnPlanHome planHome = (ZConnPlanHome)PortableRemoteObject.narrow(obj, ZConnPlanHome.class);
    ZConnPlan plan = planHome.create(engineName);
    

    User credentials are propagated from the client to the engine, the client need to be authenticated otherwise the engine will reject the request.