I recently saw a post that explained in JAVA EE, instead of using a .properites file, a better way to specify Configuration Properties is in a web.xml file and then injecting them inside the Class where the properties are needed.
This is my Web.xml
<env-entry>
<env-entry-name>pacakageName.ClassName/number</env-entry-name>
<env-entry-type>java.lang.Integer</env-entry-type>
<env-entry-value>123</env-entry-value>
</env-entry>
<env-entry>
<env-entry-name>country</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>Spain</env-entry-value>
</env-entry>
And in my Java class, when I use the JNDI way I am able to get the value
InitialContext initialContext = new javax.naming.InitialContext();
String countryName = (String) initialContext.lookup("java:comp/env/country");
This works, but when I try to use the new way of using #Resources and injecting the value, the value is not read from the web.xml
#Path("loginService")
public class LoginService{
#Resource() int number;
//constructor and other methods
}
I am using Tomcat 7...Could anyone help me out what I am doing wrong.
I referred this doc:
http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/env_entry/env_entry.html
Your class is not the kind that supports the #Resource annotation. It needs to be a Java EE component, like an EJB for example.
This is because the container is the one that injects the resources, and it only considers components as valid injection targets. Also for this reason the resource must be defined before the container starts, so you can't inject resources that you put into JNDI during runtime.
Make sure you have beans.xml file in WEB-INF folder (this enables CDI) and then change your variable to java.lang.Integer like this:
#Resource(name="pacakageName.ClassName/number")
Integer number;
#Resource(name="country")
String country;
It works fine in Java EE 6 container that supports CDI for example WebSphere Liberty profile
Related
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.
For various reasons I need to perform a manual lookup of SessionContext. In JBoss5, the solution
InitialContext initialContext = new InitialContext();
SessionContext sessionContext = (SessionContext) initialContext.lookup("java:comp/EJBContext");
has served med well, but from JBoss 7 I instead get a
javax.naming.NameNotFoundException: EJBContext -- service jboss.naming.context.java.global.EJBContext
Has something changed in how context is looked up in JBoss 7.2, or is my deployment lacking anything vital? For reference, standard injection works fine, this is the only lookup that fails. Or am I doing something terribly wrong (besides performing a manual lookup of SessionContext)?
According to specification of Java EJB (this one is for EJB 3.2. but nothing changed about EJBContext from previous one, EJB 3.x), you can inject EJBContext into your components either using annotation #Resource or manually via lookup (section 11.15):
The container must make a component’s EJBContext interface available either through injection
using the Resource annotation or in JNDI under the name java:comp/EJBContext
Standard way of looking up for EJB resource is via EJBContext.lookup method but there is also JNDI way which is the only possibilities if you don't have already EJBContext:
Context initCtx = new InitialContext();
EJBContext ejbCtx = (EJBContext) initCtx.lookup("java:comp/EJBContext");
This is exactly what you did, so what is wrong? There are two things, which one I'm not sure about. First, with manually lookup it's sometime needed to assign resource to component with annotation at class level:
#Resource(name = "EJBContext", type = javax.ejb.EJBContext)
public class MyComponent {
...
}
but I'm not sure is it needed for EJBContext as well, I guess not. The second thing, more important and critical - according to specification once again:
EJBContext objects accessed through the naming environment are only valid within the bean
instance that performed the lookup.
this one is section 11.15.1, and the next one, section 11.15.2:
The Container Provider is responsible for providing an appropriate EJBContext object to the refer-
encing component. The object returned must be of the appropriate specific type for the bean requesting
injection or performing the lookup—that is, the Container Provider must return an instance of the SessionContext interface to referencing session beans and an instance of the MessageDrivenCon-
text interface to message-driven beans.
Those both mean that injection and lookup for EJBContext are only valid in Enterprise Java Beans, so those which are annotated with #MessageDriven, #Stateful, #Singleton or #Stateless (or described as EJBs in deployment descriptor file, also as EJB 2.x Specification). Maybe your component isn't valid EJB and it's why lookup isn't working? This is only suggestion of course.
There's one more possibilities to get EJBContext (more correctly SessionContext). Your component should implements SessionBean interface which has setSessionContext(SessionContext sessionContext) method. This method should be invoked by EJB container every time when component is used (injected somewhere, invoked by client or timeout, especially when it's created) and inside this method you should assign sessionContext parameter to bean's field.
I am writing an application in Java and I have some REST web services there. My application has following structure: http://cl.ly/L7Pv/o
REST web service classes are Stateless session beans. It works like charm. But Classes in red on the picture want to use that REST resources too.
As fas as I know I cannot use dependency injection and annotation #EJB there. I believe I have to use JNDI lookup. Documentation: http://docs.oracle.com/javaee/6/tutorial/doc/gipjf.html
But now I dont know how to write this JNDI lookup. I have tried these two:
context.lookup("java:global/diplomka/ListResource");
context.lookup("java:global/Diplomka_maven/ListResource");
What am I doing wrong? Is this a correct approach in the first place?
Thank you
If these classes (ListResource etc.) are Stateless session beans, you can put attribute name or mappedName in #Stateless annotation, e.g.:
#Stateless(mappedName="ejb/myRestService")
public class ListResource { ..
Once you have specified JNDI name of your stateless bean, it's easy to fetch the bean through JNDI lookup:
InitialContext ic = new InitialContext();
ListResource lr = (ListResource) ic.lookup("ejb/myRestService");
lr.doWhateverNeeded(..);
I am currently working on a project with multiple ejb and one ejb-jar.xml. I wonder how to share the env-entry from the ejb-jar.xml between the various ejbs.
example :
I have the following ejb-jar.xml
<session>
<ejb-name>MyBeanA</ejb-name>
<ejb-class>com.enterprise.MyBeanA</ejb-class>
<env-entry>
<env-entry-name>myVar</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>some value for my var</env-entry-value>
</env-entry>
</session>
When in the MyBeanA I use :
#Ressource
private SessionContext context;
I can get the value of myVar with the following code :
String myVar = (String) context.lookup("java:comp/env/myVar");
Is there a way to get the value of myVar in another ejb like MyBeanB ?
Hmm. There was supposed to have been a section of the assembly-descriptor where you could do this, but I see now we must have missed that before the spec went final. Shame. Will bring that up in the EG and cross my fingers it isn't too late to fix for EJB.next.
In the meantime if you have an ear, you can declare them in the application.xml and it will be available in java:app/. If you have EJBs in a .war file, you can do it in the web.xml and the EJBs will be able to see them in either java:comp or java:module.
I'm using persistence API and want to load jdbc URL from web.xml. URL should be a context parameter of servlet. I can't find how to construct EntityManagerFactory not using persistence.xml. May be I should create PersistenceUnit in servlet and set some parameters? Can you give me some short example?
Thank you
you can use method createEntityManagerFactory(String persistenceUnitName, Map properties) of class javax.persistence.Persistence . and insert all your parameters in the map
I personally find it the cleanest way to define a datasource in the servlet container usng JNDI and refer to that from the persistence.xml.
This also solves one configuration issue when migrating from test-uat-prod as I can use the same datasource name on the machines.
Yeah, I know JNDI is not popular, but this works nice and it avoids having to manipulate hte web.xml which is also wrapped in the war.
Whether you use a datasource or not, the JPA configuration goes in the persistence.xml, not in the web.xml. If you want to use JPA, provide a persistence.xml.
Define an init-param in your web.xml that points to your database url. For example, for MySQL, it would be something like this:
<init-param>
<param-name>DB_URL</param-name>
<param-value>jdbc:mysql:///MY_DB</param-value>
</init-param>
Then get this value inside your Web app (in a Servlet) using something like this:
String myDbUrl = getServletConfig().getInitParameter("DB_URL");
In JSP files you can get the value in this way:
String myDbUrl = config.getInitParameter("DB_URL");
You can retrieve any value from the web.xml by using env-entry
<env-entry>
<env-entry-name>dbUrl</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>jdbc:url:goes:here</env-entry-value>
</env-entry>
And in java
try {
Context ctx = new InitialContext();
String dbUrl= (String) ctx.lookup("java:comp/env/dbUrl");
//... create your connection
} catch (Exception e ) {
}