Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Deploying Swing App that calls EJB 1

Status
Not open for further replies.

priyaX

Technical User
Jan 12, 2005
10
US
Hi everyone.

I hope someone can point me in the right direction.

I have a Swing application that invokes an EJB and retrieves information back. This works fine in development mode.

I just want to able to deploy my Swing application now without hardcoding the name of the JNDI context. I should be able to just invoke my EJB with something like :


try
{
InitialContext ctx = new InitialContext(h);
Object o = ctx.lookup("java:/comp/env/ejb/emp");
EmpHome home = (EmpHome) PortableRemoteObject.narrow(o, EmpHome.class);
Emp remote = home.create();
list = remote.getAllEmployees();
copy = new ArrayList(list);
System.out.println("List EJB = " + list.size());
}


instead of :


try
{
InitialContext ctx = new InitialContext(h);
Object o = ctx.lookup("EmpJNDI");
EmpHome home = (EmpHome) PortableRemoteObject.narrow(o, EmpHome.class);
Emp remote = home.create();
list = remote.getAllEmployees();
copy = new ArrayList(list);
System.out.println("List EJB = " + list.size());
}


I read that I need to create an application-client.xml file and I came up with :



<application-client>
<display-name>SwingModule</display-name>
<ejb-ref>
<description>Reference to employee bean from a SWING application</description>
<ejb-ref-name>ejb/employeeBean</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>employee.EmpHome</home>
<remote>employee.Emp</remote>
<ejb-link>EJBModuleEmp.jar#Emp</ejb-link>
</ejb-ref>
<callback-handler>ui.Driver</callback-handler>
</application-client>


But I am lost on how to compile and run a Swing application that references an EJB. Please can some1 illustrate or point me to the right location how I can accomplish this.

P.s, I am not using any IDE's and would prefer any answers to take this into consideration.

Thanks alot

Priya
 
Have a search in Google for the 'ServiceLocator' and 'Business Delegate' patterns. You should use these methods when using your remote services.

Also, you should have a jndi.properties file on your classpath which contains the connection configuration properties for the JNDI provider. For example, to connect to the JBoss JNDI provider, the file needs to contain:-
Code:
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://localhost:1099
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces

Tim
 
I'm already using the ServiceLocator, Singleton and Business Delegate. However, these patterns are only helpful for architectural design and not really part of the deployment process.

I'm really after the process on how you JAR up and deploy a swing application that references EJB. and how you subsequently run the code.

My code is running perfectly communicating to the EJB so I don't need any help on that side, i.e Initial Conext Factories etc. I just need the standard approach to deploying a swing application that references EJB's ??

Surely some1 has done this ??


 
I don't believe there is any special consideration required for JARing up the client. Just JAR all your client code together and make sure the jndi.properties is in there too. The remote interface classes to your EJBs should be on the classpath too.

You run the JAR as normal. Don't think there's anything else to it. I certainly didn't use any application-client.xml stuff in mine.

Are you asking how to create a JAR file?

Tim
 
No, using Jar is okay .... its the problem of trying to resolve EJB names that are referenced in the swing app. If you hard-code the JNDI name (bad practice) then ur right, no deployment descriptor file is required.

JNDI.Properties is only required if you do not indirectly supply any information to a call to InitialContext. I'm supplying a Hashtable that contains fields for :

INITIAL_CONTEXT_FACTORY
PROVIDER_URL
SECURITY_CREDENTIALS
SECURITY_PRINCIPAL

Hence, no JNDI.properties needs to be supplied.

How do you get an EJB Home ?

do u specify a lookup as java:/comp/env/ejb/EJBNAME

Because this needs to be resolved in a descriptor file , or so that seems to be my understanding


Priya
 
The descriptor file is used by the EJB container to load the various EJB Home and Component interfaces into the JNDI contexts - on the server. On the client you just specify the JNDI lookup just as you have done.

As for hard-coding them, it is my understanding that the JNDI entries are indirected anyway. If the EJB JNDI contexts are rewired on the server, this will happen to the indirected set of JNDI entries leaving the ones you use to remotely get at the facade EJBs unchanged.
 
I don't agree that the JNDI entries are indirected. Thats the point behind deployment descriptor files. If you move your entries to a new JNDI server or an administrator changes the names of the JNDI then you don't have to recompile any CLASS files. You just need to redeploy the descriptor files containing the new JNDI reference.

i.e
if my ejb-jar.cml was

<ejb-jar>
<display-name>EJBModuleEmp</display-name>
<enterprise-beans>
<session>
<display-name>Emp</display-name>
<ejb-name>Emp</ejb-name>
<home>employee.EmpHome</home>
<remote>employee.Emp</remote>
<local-home>employee.EmpLocalHome</local-home>
<local>employee.EmpLocal</local>
<ejb-class>employee.EmpBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>

and my Server specific ejb jar was :

<weblogic-ejb-jar>
<weblogic-enterprise-bean>
<ejb-name>Emp</ejb-name>
<reference-descriptor>
<resource-description>
<res-ref-name>jdbc/oracleResource</res-ref-name>
<jndi-name>oracleDS</jndi-name>
</resource-description>
</reference-descriptor>
<jndi-name>EmpJNDI</jndi-name>
<local-jndi-name>EmpJNDILocal</local-jndi-name>
</weblogic-enterprise-bean>
</weblogic-ejb-jar>

Then an EJB Client can invoke the EMPLOYEE Bean via :

empRemote=(Emp)((EmpHome)PortableRemoteObject.narrow(new InitialContext().lookup("Emp"),EmpHome.class)).create();

Emp is the name of the EJB that is referenced and its JNDI reference is EmpJNDI. If this is later renamed then a change has to be made to the deployment descriptor. In my understanding, is not indirected .

 
I've just done some searches on the NET regarding Swing and EJB's and one of my questions was how do you run a swing client that accesses EJB's. The hits come up with invoking the launchClient.bat program.

has anyone used this to run Java Apps that invoke EJB's ?

Please note, I can get my Swing invoking an EJB running outside of :

1) creating an application-client.xml
2) using launchClient.bat

But I can only do this when I hard-code the JNDI name. I was under the impression that hard-coding was wrong for reasons given in previous posts.

The J2EE spec talks alot about packing up EJB clients (Application based) using LaunchClient that uses the application-client.xml. Has anyone employed this process successfully ?


 
It's a while since I did this admittedly.

Yes you use the EmpJNDI to lookup the EJB.
This is its JNDI name and is defined only in the descriptor.
If you change it in the descriptor, the client will have to know the new JNDI name to continue accessing it from JNDI.
I would normally leave the JNDI names alone. If something moves around (i.e. between packages), I use the descriptors to alter the actual class location of the home interface the unchanged JNDI name references. This is the indirection I think I meant.
 
Thanks for your continued thoughts on this Tim, your reply :-

>>I use the descriptors to alter the actual class location >>of the home interface the unchanged JNDI name references. >>This is the indirection I think I meant


Was one aspect I was referring to. Exactly what descriptors are we talking about here ? ejb-jar.xml or application-client.xml - since the application-client.xml DD file is the one I am referring to.

Yes I agree, when I write EJB clients, I reference my EJB clients via :


java:/comp/env/ejb/....


notation ... and NO JNDI NAME is used in the lookup.

I was hoping for a similar concept with Swing clients, although now from what you are saying this does not exist ?

P.s

Is this the correct forum for this question ? or is EJB forum (if there is one) more appropriate ?


Priya
 
One thought does occur to me. My EJB experience is with EJB2.0. It is entirely possible you're using a more modern version.

I'm not aware of an application-client.xml descriptor. It does seem like a good idea though. If it allows you to configure the JNDI lookups without recourse to hacking your service locator about, then I would use it. I would expect there to be some kind of API that acts as a go-between from your Swing client to the remote JNDI which uses this descriptor. Maybe it's a WebLogic thing. (I've used Borland Enterprise Server so I don't know).

There is indeed a Java J2EE forum which is by far more appropriate for posts like these. Might be worth giving it a try, though it does seem like a quieter forum than this one.

Tim
 
No, application-client.xml is part of the J2EE spec so its vendor neutral. That, with tools like LaunchClient.bat etc are the *recommended* way of providing swing based-ejb clients (or so I have read).

My experience with EJB's is from 1.x upto 2.1. I've only had a need to get into swing recently since I'm an EJB developer , hence my limited knowledge on swing/ejb invocations.

It does appear from all the research I've done on the net coupled with reading the J2EE spec for EJB clients that the application-client.xml is the recommended way to go when deploying an application client that uses Swing.

However, getting everything to compile and work is very troublesome.

I've just found out that LaunchClient.bat has been renamed to RunClient.bat

This is the contents :-

Code:
@echo off
rem 
rem Set JAVA_HOME and J2EE_HOME before running this script.
rem 
rem set JAVA_HOME to the path where you have Java 2 (JDK1.2) installed.
rem
rem set J2EE_HOME to the path where you have installed this package (EJB server).
rem

echo --------------------
set JAVA_HOME=I:\lib\Java\J2SE
set J2EE_HOME=I:\lib\Java\J2EE
if not "%J2EE_HOME%" == "" goto CONT0
echo ERROR: Set J2EE_HOME before running this script.
goto END
:CONT0

if EXIST "%J2EE_HOME%\bin\setenv.bat" goto CONT1
echo "%J2EE_HOME%\bin\setenv.bat" not found
echo ERROR: Set J2EE_HOME to the path of a valid j2sdkee ok
goto END
:CONT1

call %J2EE_HOME%\bin\setenv.bat

if not "%JAVA_HOME%" == "" goto CONT2
echo ERROR: Set JAVA_HOME before running this script.
goto END
:CONT2

if EXIST "%JAVA_HOME%\bin\java.exe" goto CONT3
echo ERROR: Set JAVA_HOME to the path of a valid jdk.
goto END
:CONT3


@echo on
%JAVACMD% %VMARGS% -Djms.home=%JMS_HOME% -Djms.properties=%J2EE_HOME%\config\jms_client.properties -Djava.security.policy==%J2EE_HOME%\lib\security\client.policy -Djava.security.auth.login.config=%J2EE_HOME%\lib\security\login.config -Dcom.sun.enterprise.home=%J2EE_HOME% -classpath %CPATH%;%APPCPATH% com.sun.enterprise.appclient.Main %*


:END

So I think I'm on the right tracks.
 
I detect a slight hole in my knowledge here [blush]. I'm gonna have to look into it to see if I should be using this method too! There's always something to learn in this game, yes?

You ask the question and I end up being the one learning [bigsmile].

TIm
 
Well if its any consolation, I have every single sun certification (java based) going apart from certified mobile whatyoumacallerit and i'm still learning !!!
 
Hello,
I've just read over your post and was wondering what your final outcome was. How are you deploying your client apps (getting them actually running on client machines?)

Also, I was wondering if you happen to know the answer to this question I've been trying to figure out:

I know that clients can look up objects and resource through my initial context. However I want my server beans to be able to call methods on my client apps. Is this possible? Do I have to resort to messaging? I've spent about 2 weeks reading through sun j2ee tutorial -- am sort of a newbie, any higher level discussion of these issues would be greatly appreciated.

Brief description of problem:
Client machines store information on server. Other clients grab information with swing based gui, use information in collaborative environment (clients interact with eachother) and store it again. Is J2EE even a good choice for this? I started writing a multithreaded socket server but turned to j2ee hoping to deploy a more powerful/scalable/reliable system.

Thanks,
Alex
 
Hello,

I've forgotten to add a dimension to my questions. I was wondering if enabling the ejbs to call procedures on client apps means that i have to start an rmi server on each client machine. If so, do people do this? How do they do so?

Thank you,
Alex
 
Hi Priya,
My envt is Swing Client connecting to Weblogic 8.1 Server.
Here is a swing HelloWorld which gets an Login EJB.
Step 1: The JNDI Name and others that are needed are stored in say: build.properties file as shown below.
*********************************************
jndi.provider.url = t3://localhost:7001/
jndi.factory = weblogic.jndi.WLInitialContextFactory
loginEJB.name = Login
*********************************************

Step 2: Have a Properties class which reads this file


import java.util.*;
import java.io.*;
import javax.naming.*;

/**
* Properties file helper. Helps read values from
* properties file easily.
*/
public class Props {

// The build.properties file name used with the examples.
private static String FILE_NAME = "build.properties";
private static Properties props = null;

/**
* Get an instance of the build.properties file.
*/
private static void getInstance(){
props = new Properties();
try{
props.load(new FileInputStream(FILE_NAME));
}
catch(IOException e){
System.out.println("PROBLEM FINDING FILE NAME "
+ FILE_NAME + " ... EXITING ...");
System.exit(1);
}
}

/**
* Return a property value given a name and create
* properties file handle if doesn't already exist.
*/
public static String get(String name){
if(props == null){
getInstance();
}

return (String) props.get(name);
}

/**
* Construct a JNDI initial context from the
* properties file info.
*/
public static Context getInitialContext(){
Context ctx = null;

// Get properties for naming service
String jndiFactory = Props.get("jndi.factory");
String providerURL = Props.get("jndi.provider.url");

// Create hashtable of JNDI properties
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, jndiFactory);
env.put(Context.PROVIDER_URL, providerURL);

// Return handle to JNDI context
try{
ctx = new InitialContext(env);
}
catch(Exception e){
System.out.println("PROBLEM CREATING JNDI CONTEXT...EXITING...");
System.exit(1);
}

return ctx;
}
}

Step 3:
HelloWorldApp which gets Login EJB and shows it on the
label.

import javax.swing.*;
import javax.naming.*;
import javax.ejb.*;
import java.rmi.*;
import javax.rmi.PortableRemoteObject;
import com.bea.EJBC.ejbs.login.*;
public class HelloWorldApp {

private LoginHome home;
private Login login;

Public HelloWorldApp() {
JFrame frame = new JFrame("Hello World");

try {
InitialContext initialContext = (InitialContext)Props.getInitialContext();;


System.out.println("before home");

home = (LoginHome)
initialContext.lookup(Props.get("loginEJB.name"));


System.out.println("Passed home");


login= (Login)home.create();


System.out.println("got login = "+login);

System.out.println("Got Login");
} catch(Exception e) {
System.out.println(e);
e.printStackTrace();
}
frame.getContentPane().add(new JLabel(login.toString()));
frame.setVisible(true);

}

public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new HelloWorldApp();
}
});
}
}
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top