JNDI lookup of EJBs that reside at Web AS
<H4>When I tested several development scenarios on and with Web AS I was wondering about how to use an EJB from a standalone JAVA application. In theory everything seemed to be quite simple. So I wrote a little application to check the theory. Because I encountered some difficulties I decided to write this blog as a simple How-To guide resp. template.</H4>
<DL>
<DD>The application calls an EJB at the SAP Web AS from within a standalone Java application. The bean just
reverses a given string (e.g. TEST –> TSET)</br>
The JNDI name of the bean is <code>InnerOuterBean</code> (don´t ask why. It is like it is).</br>
The remote home interface is <code>ReverseNameHome</code> and the remote interface <code>ReverseName</code>.
<p>The purpose of this application is to show how to do a JNDI lookup on a Web AS and then call a
method of the received EJB.</p>
<p>The important thing is to know which JARs have to be available at build and runtime</p>
<p>The method first creates the javax.naming.InitialContext which is needed for lookup of
the beans home interface.</br>
To lookup objects at SAP Web AS the INITIAL_CONTEXT_FACTORY has to be defined. This is a
vendor specific implementation. In case of the SAP Web AS it is
<code>”com.sap.engine.services.jndi.InitialContextFactoryImpl”</code>.</br>
The other parameter that has to be defined is PROVIDER_URL which depends on your environment.
In general it is “<hostname>:50004” where <hostname> has to be replaced by your hostname, e.g.
“localhost” and 50004 is the port of the P4 service the Web AS is listening at. The latter
value can be adjusted via administration tools but the default is 50004.</br>
Then <code>InitialContext.lookup(“<jndi-name>”)</code> is called to receive the home interface of the bean. The
parameter <jndi-name> has to be replaced by the name of the bean that was defined in the
deployment descriptor <code>ejb-j2ee-engine.xml</code>. In my example it is <code>InnerOuterBean</code>.</br>
When lookup was successful one can cast the received object to the type of the bean home interface. This is done
by calling <code>PortableRemoteObject.narrow(…)</code></br>
If one then has the home interface the create() method of this interface can be called to receive the
RemoteInterface of the bean. This in turn can be used to call the bean´s business methods.
</p>
<p>So far the description of the coding. There is no secret about this. But, like mentioned before, it is much more
interesting to know which JARs one needs at build and runtime.</p>
<p><b>Build time JARs</b></br>
<ul>
<li><code><u><b>ejb20.jar</b></u></code>, this JAR is because we are retrieving an EJB via <code>home.create()</code>
</li><li><code><u><b><beans client JAR></b></u></code>, this file should contain the RemoteHomeInterface and RemoteInterface of the
bean.
</ul>
</p><p><b>Runtime JARS</b></br>
<ul>
<li><code><u><b>sapj2eeclient.jar</b></u></code>, this JAR encloses the class <code>com.sap.engine.services.jndi.InitialContextFactoryImpl</code>
that is the initial context factory. The JAR file can be found in directory
<code><program folder>\SAP\JDT\eclipse\plugins\com.sap.tc.ap\comp\SAP-JEE\DCs\sap.com\com.sap.engine.client.lib\_comp\gen\default\public\default\lib\java</code>
if you have SAP Developer Studio installed. Ohterwise you have to search for it at the Web AS host under usr/sap/…
</li><li><code><u><b>logging.jar</b></u></code>, this JAR is referenced by <code>sapj2eeclient.jar</code>. It can be found under
<code><program folder>\SAP\JDT\eclipse\plugins\com.tssap.sap.libs.logging\lib</code>
</li><li><u><b><code>exception.jar</code></b></u>, this JAR is also referenced by <code>sapj2eeclient.jar</code>. It can be found under
<code><program folder>\SAP\JDT\eclipse\plugins\com.sap.tc.ap\comp\SAP-JEE\DCs\sap.com\com.sap.exception\_comp\gen\default\public\default\lib\java</code>
</li><li>Additionally you need the Build time JARs also at runtime
</li></ul>
</p>
<P>
<DD><DL>
public class Main {</br>
</br>
public static void main(String[] args) {</br>
callEJB( args[0] );</br>
}</br>
</br>
public static void callEJB( String input ) {</br>
Context ctx = null;</br>
Hashtable env = new Hashtable();</br>
env.put(Context.INITIAL_CONTEXT_FACTORY,
“com.sap.engine.services.jndi.InitialContextFactoryImpl”);</br>
env.put(Context.PROVIDER_URL, “<hostname>:50004”);</br>
</br>
try {</br>
ctx = new InitialContext(env);</br>
Object obj = ctx.lookup( “InnerOuterBean” );</br>
if( obj == null ) {</br>
System.out.println( “error: ctx.lookup
fehlgeschlagen” );</br>
} else {</br>
ReverseNameHome home = (ReverseNameHome)
PortableRemoteObject.narrow( obj, ReverseNameHome.class );</br>
if( home != null ) {</br>
try {</br>
ReverseName ejb = (ReverseName) home.create();</br>
System.out.println( ejb.getReverseName( input ) );</br>
} catch( CreateException ex ) {</br>
ex.printStackTrace();</br>
} catch( RemoteException rex ) {</br>
rex.printStackTrace();</br>
}</br>
} else {</br>
System.out.println( “error: home interface wurde
nicht erzeugt.” );</br>
}</br>
}</br>
} catch (NamingException ne) {</br>
ne.printStackTrace();</br>
} finally {</br>
try {</br>
ctx.close();</br>
} catch (Exception e) {</br>
e.printStackTrace();</br>
}</br>
}</br>
}</br>
}</br>
[url=http://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.km.cm.docs/library/webas/java/accessing%20ejb%20applications%20using%20jndi.pdf]Accessing EJB Applications Using JNDI[/url]
Best regards,
Vladimir
thank you for clarifying some things regarding the JNDI names.
It would also be great to tell us in your How-To-Guide which jars are needed when using an EJB at a remote SAP Web AS.
In my example I just figured it out by try and error.
For example it is not clear to me why I need the logging.jar and exception.jar. Of course this jars are referenced by sapj2eeclient.jar but why?
Regards
Helmut