I have a JavaEE ear containing an ejb and war being deployed to GlassFish v3.1.2.2. The war contains a Jersey/Atmosphere application that is using CDI. Within the war, I have an MDB that is asynchronously receiving events it will broadcast using Atmosphere. The message I need to broadcast using Atmosphere needs to includes some links to other resources in the web application.
In order to build those links, like in other places in the code, I would like to use UriBuilder. To do so, I need access to the application's deployed context root, so I can invoke UriBuilder.fromPath(contextRoot)
This Java EE 7 article implies I can inject a ContextServlet into a CDI bean this way:
#Inject ServletContext context;
But this does not work for my MDB. I'm also only on JavaEE6 w/ Glassfish v3.
How can I access the ServletContext from an MDB hosted in my war?
I ended up solving this with the following.
Installed the deltaspike servlet module since I'm on GlassFish v3.1.2.2 which does not have CDI 1.1 which includes a provider for ServletContext out of the box.
Followed the MDB piece of this article to convert my JMS message to a CDI event and then observed that CDI event from a pure CDI bean that had the ServletContext injected in order to build out the required URLs for the Atmosphere message.
Related
I'm working on jms base wildfly application (wildfly 8, java 7). I have to use event driven library based on Rx Java. I want to send jms message from on even listener which I have to provide to library function to. The problem is that standard EJB based mechanisms for sending jms messages does not work from inside Rx Java handlers. The wild guess is that I can not inject / use annotation based EJB jms mechanisms inside Rx Java stream as they are not spawned by the EJB container (or pass EJB beans as Rx Java handlers). I have tried to send jms messages from EJB singleton as from standalone java application following tutorial like this. The problem is have with this approach is that standalone instance of wildfly can not find dependency for index factory org.jboss.naming.remote.client.InitialContextFactory. Or wildfly won't even deploy if I try to add maven dependency
<dependency>
<groupId>org.wildfly</groupId>
<artifactId>wildfly-jms-client-bom</artifactId>
<version>${version.wildfly}</version>
<type>pom</type>
</dependency>
to my application fat jar. Any ideas would be greatly appreciated as my understanding of EJB is quite lacking in this matter.
You can use EJBs without dependency injection making a lookup to InitialContext.
After code the Singleton EJB you need to know the "EJB name on JNDI registry" after that you can do:
Context ctx = new InitialContext()
MyStatlessBeanInterface bean = ctx.lookup("FULL NAME BEAN");
bean.sendJMSMessage();
Wilfly prints the EJB name in the console at deployment, but you can read about conventions in:
https://docs.jboss.org/author/display/AS71/JNDI+Reference
Also you can get more information about lookup in:
https://docs.oracle.com/cd/E16439_01/doc.1013/e13981/usclient003.htm
I have a EJB with a remote interface that I want to access from a client. I have difficulties to build the string for the JNDI lookup. Is there a command line tool which shows all register enterprise beans in the naming service? Or can I see this in a log file?
The JNDI name should look like this:
corbaname:localhost:2809#ejb/global/MyApp/MyModule/EJBName!full.package.remote.interface.Name
I’m also not really sure if my app and module name in the string is correct.
As far as I know there is no way to dump the JNDI namespace on WebSphere Liberty (there is a way to do this in WebSphere traditional).
The easiest way to check what JNDI name your EJBs are registered at, is to check the messages.log file. In the messages.log file you should see some CNTR0167I messages which indicate where the server has bound your EJBs. The messages.log file can be found in ${server.config.dir}/logs/messages.log.
Example EJB binding message:
CNTR0167I: The server is binding the com.example.DatabaseBean interface of the DatabaseBean enterprise bean in the TestProject.war module of the TestProject application. The binding location is: java:global/TestProject/DatabaseBean!com.example.DatabaseBean
For more info, check out the IBM doc:
Using enterprise JavaBeans with remote interfaces on Liberty
I have a pure JAX-RS application both in Glassfish and in jetty-servlet. I'm trying to inject some beans into Quartz job.
I've annotated Job fields with #javax.inject.Inject, but I also believe I need to make Job factory available to container, or vice versa - I'm somewhat lost here what end to start with.
How do I accomplish it?
Hi Victor without some more detail regarding your application I am going to assume you're running in a servlet container. There is no way to do it using a "pure" JAX-RS application.
However I would recommend you use CDI (Weld or OpenWebBeans). You can then use Deltaspike to enable the request context inside your Quartz job get a reference to a request scoped bean.
Enabling Weld in your servlet container is quite simple
A guide on enabling the request context outside of an HTTP request is available here
By default you cannot inject #RequestScoped beans into your quartz job (there is no HTTP request hence no request context). To work around this you can either enable the request context by following the link above OR (and probably my approach) inject #Dependent scoped beans (which do the work) into your JAX RS beans (essentially wrappers), you can then easily get references to the #Dependent scoped beans inside your quartz job.
Here is my web.xml and pom.xml for running Weld and Jersey inside jetty, you will need jetty-plus, jetty-jndi and Weld dependencies.
Here is some info about getting JNDI setup within jetty, however I do not use this method as I start jetty as an embedded container within a SE application, here is a code snippet of what I do:
String[] configurationClasses =
{
"org.eclipse.jetty.webapp.WebInfConfiguration",
"org.eclipse.jetty.webapp.WebXmlConfiguration",
"org.eclipse.jetty.webapp.MetaInfConfiguration",
"org.eclipse.jetty.webapp.FragmentConfiguration",
"org.eclipse.jetty.plus.webapp.EnvConfiguration",
"org.eclipse.jetty.webapp.JettyWebXmlConfiguration"
};
WebAppContext webapp = new WebAppContext();
webapp.setConfigurationClasses(configurationClasses);
webapp.setDescriptor("/path/to/webapp/WEB-INF/web.xml");
webapp.setContextPath("/");
webapp.setResourceBase("/path/to/webapp");
webapp.setClassLoader(Thread.currentThread().getContextClassLoader());
I have deployed an enterprise app in an EAR and a standalone web app in WAR (out side of the EAR) to the same Java EE server.
Question is can I access the local interface of the session bean in the EAR from the standalone WAR? if so can I use dependency injection (DI)?
Section 3.2.2 of the EJB 3.1 specification explicitly states that this is not portable:
Access to an enterprise bean through
the local client view is only required
to be supported for local clients
packaged within the same application
as the enterprise bean that provides
the local client view. Compliant
implementations of this specification
may optionally support access to the
local client view of an enterprise
bean from a local client packaged in a
different application. The
configuration requirements for
inter-application access to the local
client view are vendor-specific and
are outside the scope of this
specification. Applications relying on
inter-application access to the local
client view are non-portable.
In general, the solution will require at a minimum:
Some mechanism for allowing both the EAR and WAR class loaders to have visibility to the same interface class.
Some mechanism for looking up a local interface from another application. For example, java:global.
The answer anyway to both your questions is yes.
Since both the ear and war are in the same JVM, a local interface can be used. To get an instance of the session bean, you would use the global JNDI name of said bean to do either a JNDI lookup or use with the mappedName property on the #EJB annotation. Those names are standardized via the following pattern:
java:global[/<app-name>]/<module-name>/<bean-name>[!<fully-qualified-interface-name>]
Lookup would thus be if the name of your ear is my_app, your bean is MyBean.java and its local interface is com.foo.SomeBeanLocal:
InitialContext ctx = InitialContext();
SomeBeanLocal someBean = (SomeBeanLocal) ctx.lookup("java:global/my_ear/SomeBean/com.foo.SomeBeanLocal");
Injection would be:
public SomeManagedClass {
#EJB(mappedName="java:global/my_ear/SomeBean/com.foo.SomeBeanLocal")
SomeBeanLocal someBean;
}
There are two catches however:
Non-standard naming
Older Java EE implementations (e.g. JBoss AS 5.1, Glassfish 2, Websphere) used their own naming pattern. E.g. JBoss AS 5.x would use:
<app-name>/<bean-name>/local|global
E.g. with the same names as the previous example, the global JNDI name of that bean in JBoss AS 5.1 would be:
my_app/MyBean/local
As said, other old application servers might use other names.
Startup-order
Especially with injection you have to assure somehow that the application you want to inject from has been started before the application you want to inject into. I.e. in your case that the EAR has been started before the standalone WAR. There are no standard mechanisms for this. You might be just lucky that it happens to be in the right order for you. This order might be influenced by time-stamps, alphabetical order of application names, or something else entirely.
JBoss AS for example uses <depends> tags in many of its proprietary configuration files, which is perfectly suited for this although it can be hard to find out what exactly you need to depend on (the syntax can be very cryptic).
When I try the following lookup in my code:
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
return (DataSource) envCtx.lookup("jdbc/mydb");
I get the following exception:
java.sql.SQLException: QueryResults: Unable to initialize naming context:
Name java:comp is not bound in this Context at
com.onsitemanager.database.ThreadLocalConnection.getConnection
(ThreadLocalConnection.java:130) at
...
I installed embedded JBoss following the JBoss wiki instructions. And I configured Tomcat using the "Scanning every WAR by default" deployment as specified in the configuration wiki page.
Quoting the config page:
JNDI
Embedded JBoss components like connection pooling, EJB, JPA, and transactions make
extensive use of JNDI to publish services. Embedded JBoss overrides Tomcat's JNDI
implementation by layering itself on top of Tomcat's JNDI instantiation. There are a few > reasons for this:
To avoid having to declare each and every one of these services within server.xml
To allow seemeless integration of the java:comp namespace between web apps and
EJBs.
Tomcat's JNDI implementation has a few critical bugs in it that hamper some JBoss
components ability to work
We want to provide the option for you of remoting EJBs and other services that can > be remotely looked up
Anyone have any thoughts on how I can configure the JBoss naming service which according to the above quote is overriding Tomcat's JNDI implementation so that I can do a lookup on java:comp/env?
FYI - My environment Tomcat 5.5.9, Seam 2.0.2sp, Embedded JBoss (Beta 3),
Note: I do have a -ds.xml file for my database connection properly setup and accessible on the class path per the instructions.
Also note: I have posted this question in embedded Jboss forum and seam user forum.
Thanks for the response toolkit.... yes, I can access my datasource by going directly to java:jdbc/mydb, but I'm using an existing code base that connects via the ENC. Here's some interesting info that I've found out ....
The above code works with JBoss 4.2.2.GA and here's the JNDI ctx parameters being used:
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces:
org.jboss.naming:org.jnp.interfaces
The above code works with Tomcat 5.5.x and here's the JNDI ctx parameters being used:
java.naming.factory.initial=org.apache.naming.java.javaURLContextFactory
java.naming.factory.url.pkgs=org.apache.naming
The above code fails with Embedded JBoss (Beta 3) in Tomcat 5.5.x with the above error message.
java.naming.factory.initial=org.apache.naming.java.javaURLContextFactory
java.naming.factory.url.pkgs=org.apache.namingThe above code fails with the above error using JBoss Embedded in tomcat 5.5.x
Anyone have any thoughts I what I need to do with configuring embedded JBoss JNDI configuration?
java:comp/env is known as the Enterprise Naming Context (ENC) and is not globally visible. See here for more information. You will need to locate the global JNDI name which your datasource is regsitered at.
The easiest way to do this is to navigate to JBoss' web-based JMX console and look for a 'JNDIView' (not exactly sure of the name - currently at home) mbean. This mbean should have a list method which you can invoke, which will display the context path for all of the JNDI-bound objects.
I had some similar issue with Jboss Embedded and i finally fix playing in the file:
test-Datasource-ds.xml
adding
<mbean code="org.jboss.naming.NamingAlias" name="jboss.jmx:alias=testDatasource">
<attribute name="FromName">jdbc/Example DataSource</attribute>
<attribute name="ToName">java:/testDatasource</attribute>
</mbean>
The problem was jboss add the prefix java:/ for all data source declared. So finally i had a datasource named testDatasource, overrided with that directive to jdbc/Example DataSource
Hope it works