How to access EJB on remote server? - java

I am using a GlassFish-3.1.2 server running in my subnet (192.168.1.3:3700). I already deployed an enterprise app including an EJB in which i defined a business method. Now I want to remotely access the EJB from my java application client. How do i have to setup the JNDI resp. the InitialContext object for doing the lookup of the EJB ? How do I need to define the properties? Btw. I had to run "asadmin enabled-secure-admin" in order to make the GlassFish server work on the LAN. Probably I also need to send my credentials with the properties ?
Here's my current "solution", which seems to be completley wrong :
Properties props = new Properties();
props.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");
props.setProperty("org.omg.CORBA.ORBInitialHost", "192.168.1.3");
props.setProperty("org.omg.CORBA.ORBInitialPort", "3700");
InitialContext ctx = new InitialContext(props);
TestentityFacadeRemote tfr = (TestentityFacadeRemote)ctx.lookup("java:global/TestEE/TestEE-ejb/TestentityFacadeRemote");
When I run this programm, it just waits infinitely...
Any help highly appreciated!

I solved the problem by setting the host and port directy by System.setProperty() and using the default constructor for initializing the InitialContext(). Note that the following lines should be the very first in your program / main method:
public static void main(String[] args) {
System.setProperty("org.omg.CORBA.ORBInitialHost", "192.168.1.3");
System.setProperty("org.omg.CORBA.ORBInitialPort", "3700");
InitialContext ctx = new InitialContext();
TestentityFacadeRemote tfr = (TestentityFacadeRemote)ctx.lookup("java:global/TestEE/TestEE-ejb/TestentityFacadeRemote!com.acme.remote.TestentityFacade");
}
Hope this helps ...

Related

Can't get Remote EJB to work with EJB Client API on Wildfly

I'm currently struggling with getting remote EJB invocation to work on wildfly (8.x and 9.x).
In detail it's about remote invocation from a standalone client application (not from another app server) using the EJB Client API approach. The remote naming approach works for me but isn't applicable in my scenario because I need to use client-side interceptors for passing context data to a server-side interceptor for the remote invocations.
But for now I try to get remote invocations with the client API to work for a simple example. Therefore I tried the quickstart for remote ejb invocation which is available on github (wildfly/quickstart/ejb-remote). The point is that this quickstart raises the same error as my on simple sample app. Here are some details of my application:
My remote interface:
package test.ejb;
public interface HelloRemote {
String greet(String name);
}
My Bean implementation:
package test.ejb;
import javax.ejb.Remote;
import javax.ejb.Stateless;
#Stateless(name = "Hello")
#Remote(HelloRemote.class)
public class HelloBean implements HelloRemote {
public String greet(String name) {
return "Hello " + name;
}
}
The remote view of the bean is correctly registered at the server (in export namespace):
java:jboss/exported/ejb-test-backend.jar/Hello!de.coryx.HelloRemote
Here now the client side:
My Main class:
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.jboss.ejb.client.EJBClientContext;
import test.ejb.HelloRemote;
public class Main {
public static void main(String[] args) throws Exception {
Properties props = new Properties();
props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
Context context = new InitialContext(props);
String jndiLookup = "ejb:/ejb-test-backend.jar/Hello!" + HelloRemote.class.getName();
HelloRemote hello = (HelloRemote) context.lookup(jndiLookup);
System.out.println(hello.greet("World"));
}
}
The jboss-ejb-client.properties (packaged in jar/META_INF):
endpoint.name=client-endpoint
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
remote.connection.default.host=localhost
remote.connection.default.port=8080
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
When I execute the main Method I get the following error message (same thing occurs when trying the wildfly quickstart that I mentioned above):
Exception in thread "main" java.lang.IllegalStateException: EJBCLIENT000025: No EJB receiver available for handling [appName:, moduleName:ejb-test-backend.jar, distinctName:] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext#497470ed
at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:774)
at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:116)
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:186)
at org.jboss.ejb.client.EJBInvocationHandler.sendRequestWithPossibleRetries(EJBInvocationHandler.java:255)
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:200)
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:183)
at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:146)
at com.sun.proxy.$Proxy0.greet(Unknown Source)
at Main.main(Main.java:16)
When I use the remote naming approach everything is fine:
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
props.put(Context.PROVIDER_URL, "http-remoting://127.0.0.1:8080");
props.put("jboss.naming.client.ejb.context", true);
props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
props.put("jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false");
Context context = new InitialContext(props);
String jndiLookup = "/ejb-test-backend.jar/Hello!" + HelloRemote.class.getName();
HelloRemote hello = (HelloRemote) context.lookup(jndiLookup);
System.out.println(hello.greet("World"));
Output here is (as expected):
Hello World
So is there anyone who knows what could be wrong here or better, who has a working example for remote EJB invocation on Wildfly using the EJB client API?
Thanks in advance!
As so often, I stumbled over the solution shortly after writing down the question and talking about it.
The problem with this setup was that the jboss-ejb-client.properties file has not been loaded by the client API which was then missing the connection url, ...
I don't know whether there where changes to the required location where these properties have to be placed or whether I was too dumb to read it correctly or whether I just adapted a tutorial that was corrupted. It doesn't even matter ;)
The solution is to place the properties file toplevel on the classpath and not in the META-INF directory of the JAR!
It works now as expected and I can register client-side interceptors.

Getting NullPointerException when running simple JMS

Am trying to run a simple JMS app, sadly got NullPointException . following are the links to the files of the app :
1. Producer.java
2. SynchConsumer.java
Tools used : Eclipse & GlassFish
following is the exception
Exception in thread "main" java.lang.NullPointerException
at coreservlets.Producer.main(Producer.java:96)
Any flash put into this shall be appreciated .
If you run your stand-alone application without any container around it, the #Resource injections will not work. Instead you have to do manual JNDI lookups for both the connection factory and the queue/topic:
Example:
final Properties initialContextProperties = new Properties();
final String factory = "jms/ConnectionFactory";
final String queueName = "jms/Queue";
//
final InitialContext ic = new InitialContext(initialContextProperties);
final QueueConnectionFactory qcf = (QueueConnectionFactory) ic
.lookup(factory);
final Queue queue = (Queue) ic.lookup(queueName);
As for the configuration of the InitialContext, look here: Glassfish V3.x and remote standalone client
connectionFactory.createConnection();
connectionFactory, even if static, is never initialized. For this reason it is null and you get the null pointer when you try to access the method inside it.
Two way of fixing.
If the method is static, don't declare the var, just call:
ConnectionFactory.createConnection();
If the method is not static (strange, for a class that is static), you have to do something like:
private ConnctionFactory connectionFactory = new ConnectionFactory();

Java: Multiple Data Resources inside the same servlet

"javax.naming.Context" is commonly used inside Java EE development. It's quite convenient to use it to establish dynamical database connection by calling its lookup function with given names of resources inside context.xml. The sample code is shown as following where "db_name" is the name you used to identify the database resource.
Context ctx = new InitialContext();
DataSource ds = ctx.lookup("java:comp/env/jdbc/db_name");
My concern is what are the differences between lookup resources by using the same context and lookup resources by using different contexts. And which approach makes more sense or suitable? Suppose all database resources are defined inside the same context.xml file. For example:
Context ctx = new InitialContext();
DataSource ds1 = ctx.lookup("java:comp/env/jdbc/db_name_ds1");
DataSource ds2 = ctx.lookup("java:comp/env/jdbc/db_name_ds2");
and
Context ctx_ds1 = new InitialContext();
Context ctx_ds2 = new InitialContext();
DataSource ds1 = ctx_ds1.lookup("java:comp/env/jdbc/db_name_ds1");
DataSource ds2 = ctx_ds2.lookup("java:comp/env/jdbc/db_name_ds2");
Thank you for your sharing.
there is no difference except you created an unnecessary extra java object. however, if the jndi server was remote, you would have created two different network connections and iverhead of managing them - definetly not what one should do.

Where is the JNDI name in my code?

I have created a EJB2.0 using Eclipse 3.7 IDE, and deployed it in JBoss 5 application server (my bean name is product). I am doing normal context lookup (and other stuff to call ejb), and I am able to call EJB successfully. Now my question is what is JNDI name exactly, and where did it get used in all this. Is my bean name the JNDI name, or is this my JNDI name -> org.jnp.interfaces.NamingContextFactory. Where is the JNDI name in this?????
my code:-
// initial code.............
Context ctx = getContext();
Object obj=ctx.lookup("Product");
ProductHome home =(ProductHome) javax.rmi.PortableRemoteObject.narrow(obj,ProductHome.class);
ProductRemote remote=home.create();
Product prd = new rohit.Product("PRDCamera",001,50.50) ;
remote.addProduct(prd);
remote.updateProduct(prd);
remote.removeProduct(001);
remote.findProduct(001);
remote.findAllProduct();
// getContext Method
public static InitialContext getContext() throws Exception{
Properties pro = new Properties();
pro.put(javax.naming.InitialContext.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
pro.put(javax.naming.InitialContext.PROVIDER_URL,"localhost:1099");
return new InitialContext(pro);
}
There is no JNDI name in your code.
This is how you look up EJBs in EJB 2.0:
Object ejbHome = initialContext.lookup("java:comp/env/com/mycorp/MyEJB");
MyHome myHome = (MyHome)javax.rmi.PortableRemoteObject.narrow(
(org.omg.CORBA.Object)ejbHome, MyHome.class);
The JNDI name is java:comp/env/com/mycorp/MyEJB in this case.
In the much saner EJB 3.0, you just do
MyEJB myEJB = initialContext.lookup("java:comp/env/com/mycorp/MyEJB")
and do away with the terrible home interface idea.

Is portable jndi syntax (EJB3.1) available across machines?

I was reading about "Portable Global JNDI names" in several articles, here and there for example, but I was unable to understand whether this syntax only applies to inbound machine lookups (or maybe inbound server lookup if the server is clustered).
I.e, does it only try to solve the problem of lookups between modules and apps on the same machine/server?
Because I keep seeing examples referencing to this feature and using #Remote which I would imagine can very well occur cross-machine/server.
If it indeed only resolves internal lookups to machine/server I'd appreciate it if someone could point me to the right direction with respect to how to use it with #Remote between servers (I'm guessing somewhere I need to prefix the host name).
Thanks,
Ittai
You can call EJB component from another machine that's why #Remote anotation exists.Like
String host = "10.1.1.111";
String port = "3700";
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.enterprise.naming.SerialInitContextFactory");
props.setProperty("org.omg.CORBA.ORBInitialHost", host);
props.setProperty("org.omg.CORBA.ORBInitialPort", port);
InitialContext ctx = new InitialContext(props);
TestService ejb = (TestService)ctx.lookup("java:global/XXX/XXX/TestEntityFacade!com.test.service.TestService");
ejb.findAll();
In that case you can use mention it in descriptor file then you can inject it using #EJB
#EJB(name="fooejbref")
private FooRemote fooRemote;
Within sun-web.xml :
<ejb-ref>
<ejb-ref-name>fooejbref</ejb-ref-name>
<jndi-name>corbaname:iiop:host2:3700#Foo</jndi-name>
</ejb-ref>
for details please please look this url http://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#StandaloneRemoteEJB

Categories