Storing Singleton Bean in JNDI with GlassFish 5 - java

I have a working Glassfish 5 setup inside of Eclipse.
I have modules set up like this:
common
contains remote interface for singleton bean with #remote and #local annotation
included in all other modules as a pom dependency
core
contains a singleton bean that implements the interface in common
intended to contain service classes stored in JNDI that allow any number of clients to lookup and store data and/or access other service logic
builds a war file that deploys onto GlassFish
desktop
does an InitialContext lookup of the singleton bean. (I intend to abstract this into the Service Lookup design pattern).
intended to be a desktop client that remotely accesses beans stored on the server.
Right now, I'm just trying to get it to remotely access the service in core and print some text to the console proving it worked.
I think my problem stems from a misunderstanding of how to store a custom bean in JNDI in the first place. I looked on Google, but I mostly find articles and answers to questions telling me to add name and mappedName to the Singleton annotation or they only show how to add a predefined bean into JDNI such as a Boolean or String, and not something custom defined.
My bean is defined like this:
#Singleton(name = "BookService", mappedName = "ejb/BookService")
public class BookServiceImpl implements BookService {
private static final long serialVersionUID = 1L;
which results in this on the Glassfish server:
Core Server Screenshot
but nothing appears in JNDI:
JNDI Screenshot
The client does it's InitialContext lookup like this (I've tried multiple ways of writing the JNDI name):
BookService bookService = (BookService) initialContext.lookup("java:global/core/BookService");
using these configurations (I defined my domain with a base port of 8000, so every port is 8000 + something):
glashfishEnvironmentTable = new Hashtable<String, String>();
glashfishEnvironmentTable.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.enterprise.naming.impl.SerialInitContextFactory");
glashfishEnvironmentTable.put(Context.STATE_FACTORIES,
"com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
glashfishEnvironmentTable.put(Context.URL_PKG_PREFIXES, "com.sun.enterprise.naming");
//glashfishEnvironmentTable.put(Context.PROVIDER_URL, "ejbd://localhost:8080/");
// on a different host than the appserver
glashfishEnvironmentTable.put("org.omg.CORBA.ORBInitialHost", "localhost");
// optional. Defaults to 3700. Only needed if target orb port is not 3700.
glashfishEnvironmentTable.put("org.omg.CORBA.ORBInitialPort", "8037");
I get an error like this when I run it:
Exception in thread "main" javax.naming.CommunicationException: Communication exception for SerialContext[myEnv={org.omg.CORBA.ORBInitialPort=8037, java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, org.omg.CORBA.ORBInitialHost=localhost, java.naming.factory.url.pkgs=com.sun.enterprise.naming, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl} [Root exception is java.rmi.MarshalException: CORBA MARSHAL 1330446343 No; nested exception is:
org.omg.CORBA.MARSHAL: FINE: 00810007: Underflow in BufferManagerReadStream after last fragment in message vmcid: OMG minor code: 7 completed: No]
I think my InitialContext is configured properly because when I manually define the bean in JNDI like this (The ServiceFactory doesn't do anything, because I don't know how to properly extend ObjectFactory):
Bean defined in JNDI
I get this:
Exception in thread "main" java.lang.ClassCastException: javax.naming.Reference cannot be cast to common.service.BookService
Is there simple fix to this I am missing, or am I mixing oil and water trying to get an EJB Singleton into JNDI? Or am I missing something big like an EJBHome or a Servlet?
Do I need to extend the factory class to add my service classes into JDNI, or should ObjectFactory work? If I must extend the factory class, how would I go about it?
I hope I've defined the scope of the question well enough, but this is all new to me, so if anybody has experience implementing something like this, I appreciate any input that gets me closer to doing it right.

I figured it out. I did two things I shouldn't have.
I forgot to maven install my common module before building my war file... doh!
It seems that the #Remote and the #Local annotations cannot be in the same interface or it will fail (which is a shame, because I was trying to set it up so I didn't have to have two nearly identical interfaces).
Here are some more details in case someone else has a similar issue and needs to see something that works (I haven't done #Local here, because I haven't tried it yet. It should be trivial to add though):
For remote execution, you need an interface annotated with #Remote that extends Serializable (Serialization is required for Client/Server interface).
import java.io.Serializable;
public interface Remote extends Serializable{
}
import javax.ejb.Remote;
#Remote
public interface BookServiceRemote extends Remote {
public String readBook();
}
Your war file needs to contain the BookServiceImpl
import javax.ejb.Singleton;
import us.boggs.template.common.service.BookServiceRemote;
#Singleton(name = "BookService")
public class BookServiceImpl implements BookServiceRemote {
private static final long serialVersionUID = 1L;
#Override
public String readBook() {
return "Read the book.";
}
}
Your client pom.xml must include the common module and this:
<dependency>
<groupId>org.glassfish.main.appclient</groupId>
<artifactId>gf-client</artifactId>
<version>5.1.0</version>
</dependency>
Your client main method can use this by creating an InitialContext and doing a lookup(My base port was 8000, so my ORBInitialPort is 8000+37=8037):
private static Hashtable<String, String> glashfishEnvironmentTable;
static {
glashfishEnvironmentTable = new Hashtable<String, String>();
glashfishEnvironmentTable.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.enterprise.naming.impl.SerialInitContextFactory");
glashfishEnvironmentTable.put(Context.STATE_FACTORIES,
"com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
glashfishEnvironmentTable.put(Context.URL_PKG_PREFIXES, "com.sun.enterprise.naming");
glashfishEnvironmentTable.put("org.omg.CORBA.ORBInitialHost", "localhost");
// optional. Defaults to 3700. Only needed if target orb port is not 3700.
glashfishEnvironmentTable.put("org.omg.CORBA.ORBInitialPort", "8037");
}
InitialContext initialContext = new InitialContext(glashfishEnvironmentTable);
BookServiceRemote bookService = (BookServiceRemote) initialContext.lookup("java:global/core/BookService");
System.out.println(bookService.readBook());

Related

EJB 3.0 - Context.Lookup Failed loading apropriate EJB Beans

I'm working on EJB application, and i'm trying to use lookup approach but it fails at Runtime moment,
Here my code and configuration :
weblogic.xml
<ejb-reference-description>
<ejb-ref-name>
RechercheClientSMBean
</ejb-ref-name>
<jndi-name>
*****-ejb/RechercheClientSMBean/local
</jndi-name>
</ejb-reference-description>
Local Interface
#Local
public interface IRechercheClientFacade extends Facade {}
Bean Implementation
#Stateless(name="RechercheClientSMBean", mappedName="RechercheClientSMBean")
public class RechercheClientSMBean extends AbstractBean implements IRechercheClientFacade { }
web.xml
<ejb-ref>
<ejb-ref-name>RechercheClientSMBean</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>com.*****.***.app.service.common.client.RechercheClientSMBean</home>
</ejb-ref>
Bean Lookup Code
InitialContext ctx = new InitialContext();
iRechercheClientFacade= (IRechercheClientFacade)ctx.lookup("java:comp/env/RechercheClientSMBean");
It results into the following Exception :
weblogic.deployment.EnvironmentException:
The ejb-link 'RechercheClientSMBean' declared in the ejb-ref or ejb-local-ref 'RechercheClientSMBean' in the application module 'pfi.war' could not be resolved. The target EJB for the ejb-ref could not be found. Please ensure the link is correct.
I checked every possible configuration, every naming possibility but i keep getting this same problem.
PS: the project is divided into multiple modules, the lookup method is made from web container.
Many thanks in advance.
Have you tried the following:
ctx.lookup("java:comp/env/ejb/RechercheClientSMBean");

How to specify the EJB bean name in the JNDI tree in JEE7

I'm not sure if this is a generic JEE6 question or if it is a Wildfly 10/JBoss7 EAP implementation specific question.
I'm trying to specify/override the default beanName used in my EJB JNDI mapping to something more meaningful to me.
For example:
LoginManagerBean:
#Stateless
public class LoginManagerBean extends BaseManagerBean implements LoginManager {
....
}
LoginManager:
#Local
public interface LoginManager{
....
}
In this context, WF10 will automatically create a JNDI mapping for this EJB as:
ejb:myApp/myJar/LoginManagerBean!LoginManager
In the Wildfly 10 documentation for EJB naming conventions, it says
For stateless beans:
ejb:<app-name>/<module-name>/<distinct-name>/<bean-name>!<fully-qualified-classname-of-the-remote-interface>
.... ....
bean-name : This is the name of the bean for which you are doing the
lookup. The bean name is typically the unqualified classname of the
bean implementation class, but can be overriden through either
ejb-jar.xml or via annotations. The bean name part cannot be an empty
string in the JNDI name.
However, I cannot seem to find which annotation to use to specify the bean name in an annotation. If I read the docs for #EJB it states that the beanName parameter is:
The ejb-name of the Enterprise Java Bean to which this reference is mapped
So from the docs, it does not seem that the beanName is the right parameter to use.
So how can I rename my EJB beanName in the mapping to something of my choice? For instance, what annotation can I use to make the mapping read:
ejb:myApp/myJar/MyReallyCoolName!LoginManager
If you're using JBossEAP 7/WildFly 10.x then this is JavaEE 7, although the same answer applies to Java EE 6.
You only appear to be using Local interfaces, so none of the instructions that you linked apply because they are only for remote EJB clients. Therefore these statements:
In this context, WF10 will automatically create a JNDI mapping for this EJB as:
ejb:myApp/myJar/LoginManagerBean!LoginManager
are completely incorrect.
When you deploy your application all of the JNDI names are logged in the server console:
java:global/serverapp/LoginManagerBean!com.stackoverflow.p43282192.LoginManager
java:app/serverapp/LoginManagerBean!com.stackoverflow.p43282192.LoginManager
java:module/LoginManagerBean!com.stackoverflow.p43282192.LoginManager
java:global/serverapp/LoginManagerBean
java:app/serverapp/LoginManagerBean
java:module/LoginManagerBean
Most of the time you should not care about the JNDI names because in general each EJB is unique and the server will find the right implementation:
public class LoginClient {
#EJB
private LoginManager loginManager;
...
}
If you want to use JNDI lookups and you want to create more work for yourself then you can specify the bean name:
#Stateless(name="Foo")
public class LoginManagerBean implements LoginManager {
...
which yields:
java:global/serverapp/Foo!com.stackoverflow.p43282192.LoginManager
java:app/serverapp/Foo!com.stackoverflow.p43282192.LoginManager
java:module/Foo!com.stackoverflow.p43282192.LoginManager
java:global/serverapp/Foo
java:app/serverapp/Foo
java:module/Foo
and you can look these up if you must:
LoginManager loginManager = (LoginManager)(new InitialContext().lookup("java:app/serverapp/Foo"));
or using injection:
#EJB(beanName="Foo")
private LoginManager loginManager;
BTW, I'm just deploying the sample EJB jar here (serverapp.jar). Some of the names have an additional path element if you're using an EAR file.

Glassfish 4 Acessing EJBs via Standalone Application

I am trying to access an EJB via JSE Standalone application.
I was struggling a lot with JNDI Names not being found during lookup.
After some research without any solution I found in the Glassfish server log after a deploy a message stating something like:
"[glassfish 4.1] [INFO] [AS-EJB-00054] [javax.enterprise.ejb.container] [tid: _ThreadID=47 _ThreadName=admin-listener(4)] [timeMillis: 1424811833554] [levelValue: 800] [[ Portable JNDI names for EJB HelloBean:java:global/ponteWS/HelloBean!br.com.pontews.HelloRemote, java:global/ponteWS/HelloBean!br.com.pontews.HelloBean]]]
"
I tried the remote name and voilá!!! It works.
I tried the other name and did not work.
Here comes the questions:
1-Why the JNDI name is so weird???? Is there something I can do in order to avoid the package name in front of the name of the bean?
2-What is the error I get when acessing the bean directly instead the HelloRemote Interface?
Here is the HelloRemote:
package br.com.pontews;
import javax.ejb.Remote;
#Remote
public interface HelloRemote {
public String sayHello(String name);
}
Here is the Bean:
package br.com.pontews;
import java.io.Serializable;
import javax.ejb.LocalBean;
import javax.ejb.Remote;
import javax.ejb.Stateless;
#Stateless(name="HelloBean")
#LocalBean
#Remote
public class HelloBean implements HelloRemote, Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* Default constructor.
*/
public HelloBean() {
}
public String sayHello(String name) {
return "Hello," + name + ".!" ;
}
}
Here is the call that works:
Object lookup =
ctx.lookup("java:global/ponteWS/HelloBean!br.com.pontews.HelloRemote");
Here is the call that does not works:
Object lookup =
ctx.lookup("java:global/ponteWS/HelloBean!br.com.pontews.HelloBean");
And finally the error I get with call that does not work:
Exception in thread "main" javax.naming.CommunicationException: Communication exception for SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.url.pkgs=com.sun.enterprise.naming, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl} [Root exception is java.rmi.RemoteException: CORBA NO_IMPLEMENT 1398079489 Maybe; nested exception is:
org.omg.CORBA.NO_IMPLEMENT: ----------BEGIN server-side stack trace----------
org.omg.CORBA.NO_IMPLEMENT: WARNING: 01000001: Missing local value implementation vmcid: SUN minor code: 1 completed: Maybe
:
:
:
Caused by: java.lang.ClassNotFoundException: br.com.pontews.EJB31_Generated__HelloBean__Intf____Bean (no security manager: RMI class loader disabled)
Thanks
The name you are using to lookup () has the format as specified by the EJB specification.
In case of glassfish it should also be possible to use the fully qualified name of the remote business interface to lookup the bean (https://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#SessionBeanGlobalJNDINameAssignment). In your case this would be
br.com.pontews.HelloRemote
If you still have problems on the lookup the instructions here might help: (from https://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#StandaloneRemoteEJB)
Step 1. Use the no-arg InitialContext() constructor in your code.
The most common problem developers run into is passing specific JNDI bootstrapping properties to InitialContext(args). Some other vendors require this step but GlassFish does not. Instead, use the no-arg InitialContext() constructor.
Step 2. Pass the global JNDI name of the Remote EJB to InitialContext.lookup()
Stand-alone java clients do not have access to a component naming environment (java:comp/env) or to the #EJB annotation, so they must explicitly use the global JNDI name to lookup the Remote EJB. (See here for more information on how global JNDI names are assigned to EJB components) Assuming the global JNDI name of the Remote EJB is "FooEJB" :
For Beans with a 3.x Remote Business interface :
Foo foo = (Foo) new InitialContext().lookup("FooEJB");
Note that in the EJB 3.x case the result of the lookup can be directly cast to the remote business interface type without using PortableRemoteObject.narrow().
For EJB 2.1 and earlier session/entity beans :
Object homeObj = new InitialContext().lookup("FooEJB");
FooHome fooHome = (FooHome)
PortableRemoteObject.narrow(homeObj,FooHome.class);
Foo foo = fooHome.create(...)
Step 3. Include the appropriate GlassFish .jars in the java client's classpath.
For GlassFish 3.
Include $GLASSFISH_HOME/glassfish/lib/gf-client.jar in the client's classpath.
E.g., assuming the application classes are in /home/user1/myclasses and the main client class is acme.MyClient :
java -classpath $GLASSFISH_HOME/glassfish/lib/gf-client.jar:/home/user1/myclasses acme.MyClient
Note that the Java EE 6 API classes are automatically included by gf-client.jar so there is no need to explicitly add javaee.jar to the classpath. gf-client.jar refers to many other .jars from the GlassFish installation directory so it is best to refer to it from within the installation directory itself rather than copying it(and all the other .jars) to another location.
Note: gf-client.jar is located in $GLASSFISH_HOME/modules/gf-client.jar in GlassFish v3.

Inject remote ejb glassfish 4 with #producer error WELD-000044 Unable to obtain instance from null

Well, I've got some problem injecting a remote stateless EJB into another stateless EJB using a producer with Glassfish 4.0 build 89 (development environment is NetBeans 7.0).I will use a simplified naming for this purpose but my dev structure is roughly the same, that is:
ProjectA (Enterprise Application - the one used by clients)
ProjectA-ejb
ProjectA-war
lib/ProjectB-ejbClient.jar
lib/ProjectB-jpa.jar
ProjectB (Enterprise Application - behind the curtains)
ProjectB-ejb (Contains remote ejb impl)
ProjectB-ejbClient (Java class library)
Contains remote interfaces, producer, qualifier and META-INF/beans.xml
ProjectB-jpa (java class library)
Contains entites and META-INF/persistence.xml
ProjectB contains some authorization/management beans that will be used by many other projects (even on other servers) so they are remote. Later I will add a management webapp to it, so this is why it's an enterprise app and not a simple ejb project.
ProjectA instead is a complete enterprise project with ejb+webapp (and I could later add other enteprise projects ProjectC, D, etc) that uses ProjectB services.
Inside ProjectB-jpa are stored entites shared between management project (ProjectB) and single webapps (ProjectA and others).
Inside ProjectB-ejbClient class library I've writter the qualifier as this:
#Qualifier
#Target({TYPE, METHOD, FIELD, PARAMETER})
#Retention(RUNTIME)
#Documented
public #interface RemoteManagement {
}
and a bean factory producer as this:
public class ManagementBeanFactory {
#Produces
#RemoteManagement
#EJB(lookup = "java:global/ProjectB/ProjectB-ejb/Management!it.mgmnt.ejb.ManagementRemote")
private ManagementRemote managementRemote;
}
The beans.xml file is a plain JavaEE 7 template-like with attributes version="1.1" bean-discovery-mode="all" declared (I took it from Oracle tutorial).
Now, in ProjectA-ejb I have something like this:
#Stateless
#LocalBean
public class AccessControl {
public final static String APPLICATION_CODE = "GDS";
#Inject
#RemoteManagement
//#EJB(lookup = "java:global/ProjectB/ProjectB-ejb/Management!it.mgmnt.ejb.ManagementRemote")
private ManagementRemote mr;
public String performLogin(final String username, final String password) {
String uid = mr.authenticate(username, password, APPLICATION_CODE);
return uid;
}
//...
}
Projects are both deployed without any problem but when performLogin is called from the web tier I got a javax.ejb.EJBException with root cause org.jboss.weld.exceptions.NullInstanceException: WELD-000044 Unable to obtain instance from null.
I've debugged step-by-step and I found that AccessControl.mr is a reference to the remote bean and it's not null, so producer is generating a proxy to make the call.
If I swap #Inject #RemoteManagement annotatin with commented one #EJB(lookup = "...") everything works flawlessly.
I suspect that Weld is creating a proxy on AccessControl.mr property to the ManagementBeanFactory.managementRemote property that, I think, is null.
With debugger I discovered that the "toString()" references (printed on AccessControl.mr) are completely different between #Inject and #EJB and seems that #EJB has different "type" of generated proxy.
The strange thing is that I used to do the same thing with JBOSS AS 7.1.1Final using JavaEE 6 beans.xml (has different namespaces, etc) and it worked like a charm.
I don't know if I missed something in the producer/qualifier or if something has changed from JavaEE 6 to 7 (needed because I use a lot of stateless JSF views and #ViewScoped beans) on this field...or even if it's a Glassfish/Weld flaw (as I suspect).
I don't want to use Wildfly AS before it goes final and I would try to keep development and runtime in sync (same appserver) to have a more predictable environment.
If you even find errors or have suggestions in project structure/organization, please let me know. I'm glad to receive hint to get better project style.
Thank you for your help.

#EJB annotation does not work for initialize bean within the EJB application

I have a Maven project with this structure:
-myproject
-myproject-ear
-myproject-service
-webservice
-myproject-ejb
In the myproject-ejb I have this java packages:
-src/main/java/
-src/test/java/
I have an EJB and the corresponding bean implementation in
-src/main/java/org/mypackage/MyBean.java
-src/main/java/org/mypackage/MyBeanImpl.java
In src/test/java/ I have a test called MyBeanTest.java with the following code:
import javax.ejb.EJB;
import org.mypackage.MyBean;
import org.junit.*;
public class MyBeanTest {
#EJB
private MyBean myBean;
#Test
public void testBean() {
System.out.println("myBean: "+myBean); // prints null
myBean.writeToDB("Hello", "World"); // fails since myBean is null
}
}
When I run the unit test, the myBean is null. I am wondering why the #EJB annotation does not work. The test package is in the same application as the bean, so #EJB should work.
Any ideas?
EDIT 1
I found this link with the same problem as I have, but the solution there doesn´t seem to work for me. Am I doing anything wrong?
package org.myproject.ejb;
import java.util.Hashtable;
import java.util.Properties;
import javax.ejb.EJB;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import org.myproject.ejb.MyBean;
import org.jboss.ejb.client.ContextSelector;
import org.jboss.ejb.client.EJBClientConfiguration;
import org.jboss.ejb.client.EJBClientContext;
import org.jboss.ejb.client.PropertiesBasedEJBClientConfiguration;
import org.jboss.ejb.client.remoting.ConfigBasedEJBClientContextSelector;
import org.junit.*;
public class MyBeanTest {
private MyBean myBean;
#Before
public void init() {
try {
Properties clientProp = new Properties();
clientProp.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "false");
clientProp.put("remote.connections", "default");
clientProp.put("remote.connection.default.port", "4447");
clientProp.put("remote.connection.default.host", "localhost");
clientProp.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS", "false");
EJBClientConfiguration cc = new PropertiesBasedEJBClientConfiguration(clientProp);
ContextSelector<EJBClientContext> selector = new ConfigBasedEJBClientContextSelector(cc);
EJBClientContext.setSelector(selector);
Properties env = new Properties();
env.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
env.put(Context.SECURITY_PRINCIPAL, "admin");
env.put(Context.SECURITY_CREDENTIALS, "testing");
InitialContext ctx = new InitialContext(env);
myBean = (MyBean) ctx.lookup("java:app/myproject-ejb-1.0-SNAPSHOT/MyBeanImpl");
}
catch(NamingException ex) {
ex.printStackTrace();
}
}
#Test
public void testBean() {
System.out.println("ejb: "+myBean); // prints null
}
}
The error I get with the above configuration is:
WARN: Unsupported message received with header 0xffffffff
javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:662)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:307)
at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:344)
Container resource injection, such as #EJB, requires a populated JNDI directory and only works within Java EE managed components executing in a Java EE container. Is a challenge for unit testing. See JSR318 Java EE 6 Platform Spec, section EE.5 Resources, Naming, and Injection.
You're now attempting JNDI lookup - Java SE unit test app remotely connecting its JNDI Context. Disadvantages: must deploy full Java EE 6 app as precondition to run test; test-bugfix-build-deploy-retest lifecycle can slow things.
Some issues:
Your username/password properties are different than JBoss doc;
From doc it appears JNDI lookup name needs to be "ejb:..." rather than "java:app/..." because the JBoss EJB-client-project code uses this to intercept the lookup. Also from Java EE 6 platform spec EE.5.2.2: Names in java:app namespace are shared by all components in all modules in a single Java EE app. If your test is a separate JSE app using java:app, I suspect JBoss treats it as separate to the single Java EE application, and lookup will fail.
Make sure you lookup the interface, not the implementation class (i.e. the EJB no interface view) for remote access
You're refering to an unusual reference showing direct use of EJBClientConfiguration & EJBClientContext. It seems this is not required/preferred.
Try these actions:
Include these properties:
clientProp.put("remote.connection.default.username", "admin");
clientProp.put("remote.connection.default.password", "testing");
Change client reference:
java:app/myproject-ejb-1.0-SNAPSHOT/MyBeanImpl to
ejb:<app-ear-name>/<module-jar-name>/<jboss-optional-distinct-name>/<bean-name>!<fully-qualified-classname-of-the-remote-interface>
E.g. if MyBean is a stateless EJB deployed in myproject-ejb-1.0-SNAPSHOT.jar (without any ear). Then:
ejb:/myproject-ejb-1.0-SNAPSHOT//MyBeanImpl!org.mypackage.MyBean
If it's a stateful EJB, then add "?stateful" to string.
Setup ejb-client.properties directly (via file or program) and apply directly to JNDI Context. See https://docs.jboss.org/author/display/AS72/EJB+invocations+from+a+remote+client+using+JNDI and https://docs.jboss.org/author/display/AS72/Scoped+EJB+client+contexts and http://middlewaremagic.com/jboss/?p=1177
In future: use CDI for injection; JUnit + CDI #Mock for "POJO" unit testing; Arquillian for "Java EE" unit/module testing in containers. Then you could avoid/reduce tests like (2) above (JSE client -> EJB).
CDI supports:
Java EE resource injection into POJOs (including #EJB annotation). This still requires a deployed Java EE app/component and populated JNDI directory to lookup.
Managed beans as POJOs or Java EE components (incl. EJBs) - inject "any" to "any" with superior #Inject annotation. Works without JNDI directory, is typesafe & bean scope-aware.
Supports unit testing via simple mocking. Use #Mock & #Specializes to declare replacement version for any bean. Test EJB clients without EJBs. Test EJBs as POJOs.
To enable CDI, include a beans.xml file (can be empty, if all config via annotation).
To declare a managed bean:
optional scope above class e.g. #SessionScoped
no-arg constructor / #Inject on constructor
Use this to inject a reference:
#Inject (optional #MyDeclaredQualifier) private MyBean myBean;
Arquillian ("JUnit for Java EE 6") runs test code itself on a Java EE server. It dynamically deploys test code to configured container(s) and runs tests. It supports #EJB annotation, JNDI connection becomes simple and you can include Java EE classes in unit tests without mocking, or refactoring to abstract away from them.
1) Annotation injection is done by container. So the class which is not managed(container managed) will not be able to do annotation injection.
2) Now, in this scenarios, you will have to make a manual call to JNDI and retrieve EJB instance:
ie:
InitialContext ctx = new InitialContext();
MyBean bean = (MyBeanRemote) ctx.lookup("java:global/<portable jndi name of your bean>");
Note: The use of no arg constructor InitialContext(). Because your java class is deployed in a server I presume. Or else you may need to specify context factory class if your class is a standalone java class, depending on the vendor.
Note: You will need Bean Remote interface if you are making a call to EJB from a different application (ie: different war, ear ...) or else Local interface is enough.
This exception is thrown when no initial context implementation can be created. The policy of how an initial context implementation is selected is described in the documentation of the InitialContext class.
This exception can be thrown during any interaction with the InitialContext, not only when the InitialContext is constructed. For example, the implementation of the initial context might lazily retrieve the context only when actual methods are invoked on it. The application should not have any dependency on when the existence of an initial context is determined.

Categories

Resources