A Simple Java Client Server Application using EJB3 and Glassfish3

Well, in this tutorial i want to show you how to create a simple client server application using java. Actually java has dozens of different network protocols, from a simple socket, hessian, burlap, SpringHttpInvoker, SOAP, XML and so on. But in this example, i will try to create a very simple client server application with EJB 3, using Glassfish 3 as JavaEE Container. As usual, i use Netbeans 6.9 with its default Glassfish3 installation.

First, i create a new JavaEE, EJB Module project, named CompressedEJBServer, and create a simple Stateless Session Bean in it

package com.edw.facade;

import javax.ejb.Remote;

/**
 *
 * @author edw
 */
@Remote
public interface ConnectionFacadeRemote {
    String sayHello(String string);
    int sayAge(int age);  
}

and its implementation

package com.edw.facade;

import javax.ejb.Stateless;

/**
 *
 * @author edw
 */
@Stateless
public class ConnectionFacade implements ConnectionFacadeRemote {

    public String sayHello(String string) {
        System.out.println("im at " + this.getClass().getName() + " method sayHello()");
        return "hello " + string;
    }

    public int sayAge(int age) {
        System.out.println("im at " + this.getClass().getName() + " method sayAge()");
        return age * 2;
    }
}

and that’s my EJB3 Server side files. Simple isn’t it?

Next step is creating a Standard Java Application project, for my EJB3 client application. It consist only 1 java file, for testing connection to the server.

package com.edw.main;

import com.edw.facade.ConnectionFacadeRemote;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import org.apache.log4j.Logger;

/**
 *
 * @author edw
 */
public class Main {

    private Logger logger = Logger.getLogger(Main.class);

    private void connect() {
        try {
            Properties props = new Properties();
            props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.enterprise.naming.SerialInitContextFactory");
            props.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");
            
            // glassfish default port value will be 3700, 
            // but im using tcpviewer to redirect my 50005 port to 3700
            props.setProperty("org.omg.CORBA.ORBInitialPort", "50005");

            InitialContext ctx = new InitialContext(props);
            ConnectionFacadeRemote connectionFacadeRemote = (ConnectionFacadeRemote) ctx.lookup("com.edw.facade.ConnectionFacadeRemote");
            logger.debug(connectionFacadeRemote.sayHello("edwin "));
            logger.debug("my age is " + connectionFacadeRemote.sayAge(12) + " years");
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
        }
    }

    public static void main(String[] args) {
        Main x = new Main();
        x.connect();
    }
}

include these jars to your client side’s application,

auto-depends.jar
common-util.jar
config.jar
config-api.jar
config-types.jar
connectors-internal-api.jar
container-common.jar
deployment-common.jar
dol.jar
ejb.security.jar
ejb-container.jar
glassfish-api.jar
glassfish-corba-asm.jar
glassfish-corba-codegen.jar
glassfish-corba-csiv2-idl.jar
glassfish-corba-newtimer.jar
glassfish-corba-omgapi.jar
glassfish-corba-orb.jar
glassfish-corba-orbgeneric.jar
glassfish-naming.jar
gmbal.jar
hk2-core.jar
internal-api.jar
javax.ejb.jar
javax.jms.jar
javax.resource.jar
javax.servlet.jar
javax.transaction.jar
jta.jar
kernel.jar
management-api.jar
orb-connector.jar
orb-iiop.jar
security.jar
tiger-types-osgi.jar
transaction-internal-api.jar 

and dont forget to add CompressedEJBServer project into CompressEJBClient’s project

this is what happen if i run my client side’s application

[Main] DEBUG com.edw.main.Main:30 - hello edwin 
[Main] DEBUG com.edw.main.Main:31 - my age is 24 years

this is my Server side’s project structures

and this is my Client side’s project structures
My Client Side's Project Structure

and this is my TCP Viewer logs, i try to redirect my localhost’s port 50005 into my localhost’s port 3700 (Glassfish’s port), so i can see what is passing through my 50005 port via TCP Viewer’s console.

Hope this can help, have fun and good luck. May the Source be with You.
(*)

Google+

77 Comments

Arun Gupta

about 6 years ago

Nice blog, Instead of including all the libraries in your classpath, you can also use AppClient which will automatically generate a client with all the dependencies.

Reply

Hull

about 6 years ago

MAN YOUR AWESOME, I HAVE SPENDED A LOT OF HOURS SEARCHING FOR THE MINIMAL JAR LIBS REQUIRED FOR A GFV3 EJB CLIENT. YOU ROCK! Regards from México

Reply

edwin

about 6 years ago

Thanks Hull, glad that it can help. Dont forget to Visit Indonesia, Dangerously Beautiful. :-)

gowtham

about 6 years ago

How to add these jar files to client side's application? actually i donno where they r located on my computer. I'm a newbie.

Reply

edwin

about 6 years ago

hi Gowtham, thanks for asking, you can find these jars on your glassfish installation folder, they are in modules folder. For example, in my PC is, C:\Program Files\glassfish-3.0.1\glassfish\modules.

Gerardo

about 6 years ago

Hello Edwin. Thanks for sharing. I´m also a newbie. I would like to know if you had to install client and server in a production environment, how would you install this program? How would you call the client in a user-friendly way?

Reply

edwin

about 6 years ago

Hi Gerardo, thanks for ur question. Your question is a little bit confusing, but ill try my best to answer it. I like to use exe4j to create an executable application for my client, or you could also try JNLP web start to lauch ur client application from web so you dont have to distribute ur application. Dont forget to include Glassfish libraries on ur client classpath. And how can i call the client in a user-friendly way? Well, i dont know if the server can call the client, try using java.net.Socket or java.net.SocketServer for it.

Fernando

about 6 years ago

java.lang.NoClassDefFoundError: com/sun/enterprise/module/ModulesRegistry ??? why?... I did everything...

Reply

edwin

about 6 years ago

hi fernando, you need to include hk2-core.jar from your glassfish installation lib, well in my PC it's in C:\Program Files\glassfish-3.0.1\glassfish\modules\hk2-core.jar. cheers.

Ron Albury

about 5 years ago

Thanks for helping me get closer. I have a deadline looming and I am !!Desperate!! to get this stand alone client deployed (it runs fine inside Netbeans). I believe I did everything right but I'm getting a null pointer error: SerialContext.(SerialContext.java:198). Do you have any ideas?

Reply

Ron Albury

about 5 years ago

Sorry ... me again. I discovered I had WebStart set in the NetBeans properties. It is all working now.

Reply

edwin

about 5 years ago

hi ron, i'm glad that your program is working well right now, perhaps you could share your complete exception stack trace, and how you managed to fixed it. Maybe it could help others too. Thanks before.

Jeffry

about 5 years ago

Hi Edwin, thanks for your tutorial. I have a question about the client's side application. Why everytime I build the client's side application, the EJB component is undeployed so I have to deploy it again? Thanks man, as a fellow Indonesian I'm proud of you Jeffry

Reply

edwin

about 5 years ago

hi Jeffry, thanks for the question. May i know how you deploy your EJB component, do you use netbeans' to do it or you deploy it manually? Why dont you try to manually deploy your EJB components. First build your project into an EAR application, and then upload it into Glassfish's environment.

Reply

Antonio

about 5 years ago

Hi, Thanks for this tutorial, but I have one question, this client works outside form netbeans? and in another computer? Thanks again

Reply

edwin

about 5 years ago

Hi Antonio, yes this application works well with or without netbeans, and accessible from other computer.

Shamshad Alam

about 5 years ago

@@@@@@@@@@Very very thanks to you!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Reply

edwin

about 5 years ago

anytime Shamshad, glad i can help you.

Stefanos

about 5 years ago

Hello edwin, Thanks a lot for the article.. although I had many many issues before I got it (partially) working. --the setup I have setup the server and the client separately, both with maven. I ended up using GF3.0.1 because GF3.1 has a bug with a jar - I don't remember which one now sry.. So the server jar is deployed to GF as an EJB jar. --the problem When I run the client from inside eclipse it works OK. If I package the client to a jar and run it from command line it throws a null pointer exception.. it is thrown in the line `ctx = new InitialContext(props);` $ java -Djava.util.logging.config.file=logging.properties -cp client-1.0-jar-with-dependencies.jar gr.stk.testee.client.ConverterClient 29 - 2011 1:27:19 - com.sun.enterprise.naming.impl.SerialContext FINE: SerialContext ==> SerialContext instance created : SerialContext java.lang.NullPointerException at com.sun.enterprise.naming.impl.SerialContext.(SerialContext.java:198) at com.sun.enterprise.naming.impl.SerialContext.(SerialContext.java:253) Any clues ? thanks in advance!

Reply

edwin

about 5 years ago

hi Stefanos, It's a little bit hard to see what's wrong with your application. Because i cant see both your full exception stacktrace and your source code. My wild guess is, your application couldnt find Glassfish JNDI, so it throws NullPointerException. Do you see this exception? Caused by: javax.naming.NameNotFoundException:

avinash

about 4 years ago

hi edwin, thankx for ur example. i tried this. I am able to get the "CompressedEJBServer" in glassfish admin page under "Applications" tab. when I ran the client,i could get the InitialContext object but my client code hangs while lookup for the bean (at line 29 in the Main.java under CompressedEJBClient, mentioned above). I have done all the configuration but am not able to look up. Also, I am not getting any JNDi external or internal resource on the GF admin console under JNDI tab. Kindly help me for the same.

Reply

edwin

about 4 years ago

Hi Avinash, are you trying to connect from localhost or from other ip? Perhaps your glassfish port is blocked by firewall. Please paste your configuration here, especially your org.omg.CORBA.ORBInitialHost and org.omg.CORBA.ORBInitialPort.

Jack Krauser

about 4 years ago

Can someone help me?

Reply

edwin

about 4 years ago

Hi, Jack Krauser Yes, how may i help you? Could you elaborate your problem more specific, Thank you :)

Anderson

about 4 years ago

Hi Edwin, I am Anderson, from São Paulo, Brazil... I did your tutorial but in console i have this error: java.lang.NoClassDefFoundError: com/sun/corba/ee/spi/folb/GroupInfoServiceObserver... Thanks.......

Reply

edwin

about 4 years ago

Hi Anderson, ithink you need to include glassfish-corba-orb.jar :)

exnesian

about 4 years ago

Hi Edwin... First thanks for your code sample. I need your help, Can you please give me a guide? I have to build, in my newbie state of java, a complex application. It is a java web application that will be run on the glassfish server. the application runs normally waiting for client browser request like common web based application, Say if client by using browser, requests "localhost:8080/webApplication1/index.faces" then the application on the glassfish server executes the code within "index.faces" page and all corresponding MANAGEBEAN CODE inside "index.faces" page. All so far is not really a hard work, but the problem is how to make MANAGEBEAN CODE, that is called earlier, requests some data from another computer, by TCP socket connection like usual client-server app NOT websocket, and then MANAGEBEAN CODE forwards the data to client. and finally as the result the requested data appear on client side. Simply description, there would be an architecture like: Computer A APP on Glassfih ----> Client(Browser) We could say: 1. Client communicates with Computer A INDIRECTLY through APP on Glassfih in purpose requesting some data. 2. Computer A and APP on GlashFish communicate each other in two way communication manner. APP on Glafish applies socket server while Computer A uses client socket. 3. computer-A like can be more than one connecting to APP on Glasfish say Computer A, Computer B.... Computer N! it's like more than one client connecting to server. 4. Client can choose what data form which Computer it will request by adding, for example, parameter in the url like "localhost:8080/webApplication1/index.faces?choice=Computer A" I don't know if I have explained the problem well. From my opinion of a java newbie, it's like combining web App and java socket programming. is it possible? or is there any simple solution? Sorry for addressing you my problem but I really need your help... Beforehand thank you very much! :-)

Reply

edwin

about 4 years ago

Hi exnesian, yes it's very possible. In my latest app, ive connected Struts application ( a simple web app ) to another server using ISO requests ( socket ). basically, the architecure would be like, user -- http request --> glassfish app --- iso / socket request --> another server dont forget, the hard part is how to manage your socket response fast enough, before your http request time out. after all, http request is stateless i know you can do it, afterall you are an extraordinaryindonesian right? ;)

Shahab

about 4 years ago

Hi Edwin. (Subject: Standalone remote java client cannot access EJB3 in Open Source GlassFish3.1.2 running in Eclipse-Helios-OEPE). Any help is appreciated. My simple java client: ---- package org.expense.client; import java.util.Properties; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import org.expense.stateless.ExpenseBeanRemote; public class ExpenseClient { private void standaloneTest() { try { Properties jndiProps = new Properties(); jndiProps.put("java.naming.factory.initial", "com.sun.enterprise.naming.impl.SerialInitContextFactory"); jndiProps.put("java.naming.factory.url.pkgs", "com.sun.enterprise.naming"); jndiProps.put("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl"); jndiProps.setProperty("org.omg.CORBA.ORBInitialHost", "localhost"); jndiProps.setProperty("org.omg.CORBA.ORBInitialPort", "3700"); Context ctx; ctx = new InitialContext(jndiProps); ExpenseBeanRemote expenseBeanRemote = (ExpenseBeanRemote) ctx.lookup("java:global/Expense/ExpenseEJB/ExpenseBean"); expenseBeanRemote.createItem("0001", "ITEM-1", "I"); System.out.println("Item created...."); } catch (NamingException e) { System.out.println("Expense Client Exception: "+e.getMessage()); e.printStackTrace(); } } public static void main(String[] args) { ExpenseClient expenseClient = new ExpenseClient(); expenseClient.standaloneTest(); } } ---- Proof of JNDI in GlassFish server log: [#|2012-04-16T12:28:36.146-0400|INFO|glassfish3.0.1|javax.enterprise.system.core.transaction.com.sun.jts.CosTransactions|_ThreadID=11;_ThreadName=Thread-1;|JTS5014: Recoverable JTS instance, serverId = [3700]|#] [#|2012-04-16T12:28:36.521-0400|INFO|glassfish3.0.1|javax.enterprise.system.container.ejb.com.sun.ejb.containers|_ThreadID=11;_ThreadName=Thread-1;|Portable JNDI names for EJB ExpenseBean : [java 1="java:global/Expense/ExpenseEJB/ExpenseBean!org.expense.stateless.ExpenseBeanRemote" language=":global/Expense/ExpenseEJB/ExpenseBean,"][/java]|#] [#|2012-04-16T12:28:36.521-0400|INFO|glassfish3.0.1|javax.enterprise.system.container.ejb.com.sun.ejb.containers|_ThreadID=11;_ThreadName=Thread-1;|Glassfish-specific (Non-portable) JNDI names for EJB ExpenseBean : [ejb/ExpenseEjb, ejb/ExpenseEjb#org.expense.stateless.ExpenseBeanRemote]|#] ------------- Exception upon program execution: java.lang.NullPointerException Expense Client Exception: Lookup failed for 'java:global/Expense/ExpenseEJB/ExpenseBean' in SerialContext targetHost=localhost,targetPort=3700 at com.sun.enterprise.naming.impl.SerialContext.getRemoteProvider(SerialContext.java:297) at com.sun.enterprise.naming.impl.SerialContext.getProvider(SerialContext.java:271) at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:430) at javax.naming.InitialContext.lookup(InitialContext.java:392) at org.expense.client.ExpenseClient.standaloneTest(ExpenseClient.java:35) at org.expense.client.ExpenseClient.main(ExpenseClient.java:49) javax.naming.NamingException: Lookup failed for 'java:global/Expense/ExpenseEJB/ExpenseBean' in SerialContext targetHost=localhost,targetPort=3700 [Root exception is javax.naming.NamingException: Unable to acquire SerialContextProvider for SerialContext targetHost=localhost,targetPort=3700 [Root exception is java.lang.NullPointerException]] at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:442) at javax.naming.InitialContext.lookup(InitialContext.java:392) at org.expense.client.ExpenseClient.standaloneTest(ExpenseClient.java:35) at org.expense.client.ExpenseClient.main(ExpenseClient.java:49) Caused by: javax.naming.NamingException: Unable to acquire SerialContextProvider for SerialContext targetHost=localhost,targetPort=3700 [Root exception is java.lang.NullPointerException] at com.sun.enterprise.naming.impl.SerialContext.getProvider(SerialContext.java:276) at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:430) ... 3 more Caused by: java.lang.NullPointerException at com.sun.enterprise.naming.impl.SerialContext.getRemoteProvider(SerialContext.java:297) at com.sun.enterprise.naming.impl.SerialContext.getProvider(SerialContext.java:271) ... 4 more -------------- Thanks.

Reply

edwin

about 4 years ago

the main error cause would be Caused by: javax.naming.NamingException: Unable to acquire SerialContextProvider for SerialContext targetHost=localhost,targetPort=3700 [Root exception is java.lang.NullPointerException] at com.sun.enterprise.naming.impl.SerialContext.getProvider(SerialContext.java:276) at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:430) could you please paste here all the jars you've included in your project, perhaps the main cause of the error is because of missing libraries.

Shahab

about 4 years ago

Thanks Edwin for the clue. I added the missing libraries on the client side; as per your list above in this thread. Also, I had to change my persistence.xml (I'm pasting it for anyone's reference). It worked for me now. By the way, I would appreciate if you have any sample to use "AppClient" from GlassFish to generate client. Thanks again. ------- org.eclipse.persistence.jpa.PersistenceProvider org.expense.jpa.Item org.expense.jpa.ItemExpense <!-- --> -------

edwin

about 4 years ago

Hi Shahab, you could check on my latest writings regarding the appclient feature.

Shahab

about 4 years ago

persistence.xml -------------------- org.eclipse.persistence.jpa.PersistenceProvider org.expense.jpa.Item org.expense.jpa.ItemExpense

Reply

edwin

about 4 years ago

Hi, Shahab sorry, your comment seems not working very well, could you please paste your source to other website such as pastebin, and put the link here. Thank You.

Meziano

about 4 years ago

Hello evrybody, I tried to write almost the same under maven (a maven JEE/EJB-Module and a Java SE Application), unfortunatelly I don't succed to get a connection from the "client". I am frustrated and feel like a blind: I don't know the use of all the jars and which to use. I tried almost anything. Any ideas?? Thank you in advance! Meziano

Reply

edwin

about 4 years ago

Hi Meziano, could you please paste the error stacktrce you've found? Thank You

Meziano

about 4 years ago

Hello edwin, thank you so much for your answer. I am sorry for the delay, I was very busy this week. I tried ta add the libraries or better the dependencies (when working with maven a library is a dependency, isn't it?) I get the following error message: Could not resolve dependencies for project xxx: The following artifacts could not be resolved: org.eclipse.persistence:javax.persistence:jar:2.0.3, org.eclipse.persistence:org.eclipse.persistence.core:jar:2.3.0, org.eclipse.persistence:org.eclipse.persistence.jpa:jar:2.3.0, org.eclipse.persistence:org.eclipse.persistence.jpa.modelgen:jar:2.3.0, org.eclipse.persistence:org.eclipse.persistence.oracle:jar:2.3.0, org.eclipse.persistence:org.eclipse.persistence.antlr:jar:2.3.0, org.eclipse.persistence:org.eclipse.persistence.asm:jar:2.3.0: Failure to find org.eclipse.persistence:javax.persistence:jar:2.0.3 in http://repo.maven.apache.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced -> [Help 1] I know that this menas I must provide a valide repository, where the artifacts are available. I could resolve this problem last week and I got another error, I tried to reproduce this, but I had no time. Could you please tell me which dependencies to add and which repositories are valid?? I have another problem: I am working at a JEE project, the GUI is writting by other persons. I cretaed the database, wrote a Java SE application which contains the entities (I let Netbeans generate these from database and fitted them), wrote the testclasses, wrote the ejbs and tested them. I than wrote a stateless webservice in which the other beans are injected. I the webservice, I got the expected result: it's possible to get the list of all instances (rows in the database), get an instance of an instance by ID, update and save it: all CRUD operations are OK. In the Client, a Java SE Application, I added a "web service client" by specifying the WSDL URL. All what I got are detached objects. Every object with its all fields (as strings) EXCEPT THE ID (Primary Key). From an update, I got an insert (cause the edited object has no ID on the client). Remove doesn't work at all. Other operations (findAll, findById) are OK. Do I have to use DTOs (Data Transfer Objects)??? I read that these are not more needed as of ejb3.1 On the clients, for a findAll operation, Netbeans does not acc