What is java:comp/env scope rules? - java

I understand that java:comp/env is the node in the JNDI tree where you can find properties for the current Java EE component (a webapp, or an EJB), and also I know that each EJB has its own component environment ,also there is java:global and java:app and a java:module depending on that I have some questions
when I use Context envContext = (Context)initContext.lookup("java:comp/env"); to get initContext what Context exactly I get (global,app,module,webApp or EJB Context)?
Is there is certain rules applied for searching different scopes?
Let's say I have web application with many EJBs,does this means that I have many Initial Contexts (one for webApp and one for each EJB) or all of these resources are somehow collected under one context java:comp/env?
Many Thanks.

when I use Context envContext = (Context)initContext.lookup("java:comp/env"); to get initContext what Context exactly I get (global,app,module,webApp or EJB Context)?
Quoting from TomEE documentation http://tomee.apache.org/lookup-of-other-ejbs-example.html
In a webapp, the java:comp/env namespace is shared by all servlets.
This is essentially equivalent to the java:module namespace in Java EE
6. Understand there is a conflict in definition here and that for EJBs, java:comp is scoped at the component (the EJB itself) not the
module as with webapps.
Is there is certain rules applied for searching different scopes?
Quoting from JavaEE 6 Tutorial http://docs.oracle.com/cd/E19798-01/821-1841/girgn/index.html
The java:global JNDI namespace is the portable way of finding remote
enterprise beans using JNDI lookups. The java:module namespace is used
to look up local enterprise beans within the same module. The
java:app namespace is used to look up local enterprise beans packaged
within the same application. That is, the enterprise bean is packaged
within an EAR file containing multiple Java EE modules.
Let's say I have web application with many EJBs,does this means that I have many Initial Contexts (one for webApp and one for each EJB) or all of these resources are somehow collected under one context java:comp/env?
Based on above links, you will have not have many contexts.

Regarding question 3 on the scope of java:comp/env in presence of EJBs.
Traditionally (before JEE 6) java:comp/env was module level for war modules and EJB level for EJBs in jar modules.
In that model, one has to define environment entries (via resource-ref and env-entry in ejb-jar.xml, or for resource-refs since JEE5 one could use #Resource at the class level) for every single EJB.
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>B1</ejb-name>
<ejb-class>p1.B1</ejb-class> <!-- ejb-class should be skipped if bean is already defined via annotation -->
<env-entry>
<env-entry-name>entry1</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>value1</env-entry-value
</env-entry>
</session>
</enterprise-beans>
</ejb-jar>
Since JEE 6, one can deploy EJBs as part of war module. Whether war module is deployed directly or is part or ear module, it has a single java:comp/env namespace shared between all servlets, EJBs and any other code within that module. One can define environment entries in web.xml:
<web-app>
<env-entry>
<env-entry-name>entry1</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>value1</env-entry-value
</env-entry>
</web-app>
In this war based model, one could still have ejb-jar.xml to configure other aspects of EJBs, but env-entry for a given bean in ejb-jar.xml would end up injecting the environment value for all other beans in the war.
So, I would always use war archives for everything (possibly packaged in ear).

When I use Context envContext = (Context)initContext.lookup("java:comp/env"); to get initContext what Context exactly I get (global,app,module,webApp or EJB Context)?
You get the one you asked for, the one you correctly described as 'the current Java EE component (a webapp, or an EJB)'.
Is there is certain rules applied for searching different scopes?
You search within the scope you specify. I don't know what else your question could mean.
Let's say I have web application with many EJBs, does this means that I have many Initial Contexts (one for webApp and one for each EJB) or all of these resources are somehow collected under one context java:comp/env?
The question doesn't make sense. You have as many InitialContexts as you create. They are objects. What they refer to depends on what you lookup within that InitialContext. If you keep looking up "the current Java EE component (a webapp, or an EJB)", you will keep getting exactly that. All 'these resources' are 'collected' under their own names respectively, within java:comp/env.

As far of my knowledge by default the scope will be Global

Related

Convert traditional projects to spring boot, without changing applicationContext.xml, dispatcher-servlet.xml & tomcat's context.xml

The background & requirements are:
there are a lot of old projects which have an applicationContext.xml and one or more dispatcher[-XXX]-servlet.xml. We hope those projects can still works while using spring boot(we developed a deployment tools to deploy spring boot applications, but the old projects are still deployed manually). But, #SpringBootApplication can't build the contexts as they were. And rewriting them into codes one by one costs too much, I think.
In those project, we use an extended RequestMappingHandlerMapping, so we can't use the native MVC.
the context.xml of tomcat, which contains jndi definitions, is maintained by OPs. We have to load it just like tomcat does.
i can't find where to set welcome file, which were set in web.xml
I currently using:
#Configuration
#ImportResource({"classpath:/applicationContext.xml", "classpath:/dispatcher-servlet.xml"})
Those simple projects without using jndi can startup.
But as my understanding, in this case, the applicationContext and dispatcher-servlet are in the same level(dispatcher-servlet should the child of applicationContext, isn't it?). So, i can't even ensure this one works properly.
We did a similar thing about a year ago and your setup was more or less the same as ours and importing those XML files did the trick; the only thing we had to do was to ensure our application class was in a different package hierarchy in order to avoid conflicting/duplicate bean definitions due to its inherent #ComponentScan.
And having dispatcher servlet and application context in the same context won't cause any issues - yes, dispatcher servlet's context is usually defined as a separate context and is a child of the more broad applicationContext but what most people fail to grasp is that that separation only matters if your application wants to have more than one dispatcher servlet, which is rarely the case any more, if it ever was.
In case of multiple dispatcher servlets it was a must to enable them to have different WebMVC configurations, and applicationContext was there to allow you to share common beans and configuration between your servlet contexts so that you don't have to do the same work twice.

EJB Pool and EJB defined in 2 EAR

I'm totaly newbie in EJB and i need to understand how "ejb pool" works and how it is shared between EARS.
We have an EAR (named "ear1") deployed on WebSphere 8.5. This EAR contains some Stateless EJB3 (test.Ejb1, test.Ejb2, test.Ejb3) used by business-logic for access DB (using a "SQL-DB-datasource1").
We need to build a new EAR (named "ear2") and deploy it in the same websphere, but referencing a new datasource ("SQL-DB-datasource2").
Questions:
1. the EJB pool is the same and shared between ears, right?
2. if (mistake) i use same packages and the same EJB's names in both EARs (test.Ejb1, test.Ejb2, test.Ejb3), am i risking "ejb conflicts" between the two EARS when i will reference these EJB into rest services?
3. Or each EAR has "its own context" in the EJB pool?
4. "ear2" can access EJBs defined in "ear1"?
5. depends on how i make the "EJB lookup"?
Thanks!
No, each EJB has its own pool.
No, each application is loaded by a distinct class loader (by default), which means there is no risk of conflict, only a risk of potential confusion for you.
Yes.
Yes if the EJBs have remote interfaces. Yes but with caveats if the EJBs have local interfaces; see the "Local client views" section of the EJB modules topic in the Knowledge Center.
Yes, you will need to use a lookup string. The EJB container will print a CNTR0167I message when an application is starting, which will give you the lookup string. I would recommend using the java:global lookup string with an EJB reference (#EJB annotation or <ejb-ref>/<ejb-local-ref> XML element).

What is the recommended method of storing EJB configuration? (Java version of app.config/web.config)

I must apologize for asking what was probably asked numerous times before, but after extensive search I still am not sure.
web.xml can store configuration parameters for the JSP pages and servlets. Can that be used for the bean in the same project? Otherwise is there anything similar for the beans?
The items I am looking to store would be deployment-specific strings: DB driver class, connection string and a bunch of paths to the resources.
One of the options I came across was java.util.Properties, however it would require some coding.
EDIT:
To implement the below proposed solutions I've added ejb-jar.xml to the bean project and populated it with following:
<enterprise-beans>
<session>
<ejb-name>ejbConfigurator</ejb-name>
<env-entry>
<description>Path to the directory containing images</description>
<!--env-entry-name>package.ejbConfigurator/imageBasePath</env-entry-name-->
<env-entry-name>imageBasePath</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>/home/user/NetBeansProjects/Builder/images</env-entry-value>
</env-entry>
</session>
</enterprise-beans>
The annotated variables did not get populated:
#Resource(name="imageBasePath")
private String imageBasePath;
or
#Resource private String imageBasePath;
And the code below
try {
Context ctx = new InitialContext();
this.imageBasePath = (String) ctx.lookup("java:comp/env/imageBasePath");
}
catch (NamingException ex) {
Logger.getLogger(ejbBlanketConfigurator.class.getName()).log(Level.SEVERE, null, ex);
}
threw an exception:
javax.naming.NameNotFoundException: No object bound to name java:comp/env/imageBasePath
There are several ways and depending on what's your deployment structure it may make sense to pick one or another.
META-INF/ejb-jar.xml - this is used when the EJBs are inside their own JAR which in turn is part of an EAR.
WEB-INF/ejb-jar.xml - this is used when EJBs are part of a WAR.
annotations - many configuration options can be specified through annotations on the bean class itself.
The above are configurations specific to EJBs. However, some of the resources you mention may be specified in both ejb-jar.xml and web.xml.
For reference, try reading the schema file - it's fairly well documented, or something like this.
Checkout the ejb-jar.xml and in particular the env-entry element, which allows you to inject configured items into your code
<env-entry>
<env-entry-name>some_name</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>Some configurable value</env-entry-value>
</env-entry>
and to use it with annotations:
#Resource(name="some_name")
String someString;
See http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/env_entry/env_entry.html
As another has posted, the location of the ejb-jar.xml matters depending on where your EJB jar is located.
HOWEVER
When it comes to DB driver classes and connection strings specifically, you may want to look into externally configuring datasources and then accessing the externally configured datasource from your application (via JNDI or JNDI + resource-refs usually).

Possible JNDI lookups within EJB container

I'm going through the EJB 3.1 spec and am trying to grasp the different possible ways a JNDI call can be made.
You can do it using a SessionContext and an InitialContext (or a self-created context based on the Initial- or SessionContext).
Based on which you use the syntax differs, but I can't seem to find the logic behind it.
So my question is: when can I use what syntax to use JNDI calls within an EJB container environment?
The rest of this question just serves as illustration of my point.
For example, I believe this is always possible for a correctly injected sessioncontext or created initialcontext:
ctx.lookup(java:global[/<app-name>]/<module-name>/<bean-name>[!<fully-qualified-interface-name>])
ctx.lookup(java:comp/env ...)
// special ones like these
ctx.lookup("java:comp/UserTransaction");
ctx.lookup("java:comp/ORB");
Sometimes (only for session context?) this shorter version is possible:
ctx.lookup(<bean-name>);
What about in an embedded environment, can only global references be used?
I usually inject EJBs inside EJB container with #EJB annotation. So the JDNI look ups are done by the server at deploy time.
For example JBOSS deployment:
INFO [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-2) JNDI bindings for session bean named TestBean in deployment unit subdeployment "MyEJB.jar" of deployment "MyProject.ear" are as follows:
java:global/MyProject/MyEJB/TestBean!my.project.TestBean
java:app/MyEJB/TestEJB!my.project.TestBean
java:module/TestEJB!my.project.TestBean
java:global/MyProject/MyEJB/TestEJB
java:app/MyEJB/TestBean
java:module/TestBean
Some are per EJB specification some are application server dependent.
If you have to make look ups from context I think the best way is to use java:global.
You can also find some additional info at: http://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#POJOLocalEJB
jndi is a bit like a file system. You can refer to things using a relative path based on where you are in the tree (where you "cd"-ed to).
The injected session context is by default "positioned" on java:comp, so there you reference things that are available in java:comp, without the need to provide the "full path".
Note that java:comp itself is relative to a single EJB bean, or because of historical reasons to the entire Web module.
I'm not 100% sure what you mean with embedded environment, but if the code from which you are doing the JNDI lookup is not part of any of the predefined scopes (like java:module, java:app, etc) only java:global can be portably used.

Optional datasources in java web applications

I'm creating a java web application which should run on multiple application servers (jetty, tomcat, websphere, jboss). There is an optional datasource in this application. If it is configured the application will use it, otherwise some functionality in the application will be disabled.
The problem is, if I define the resource-ref in the web.xml, it will be required to be defined in the application context. If I don't define it in the web.xml, then when I try to deploy the application in websphere, there is no way to reference the datasource in the application.
Is there a way to make websphere aware of the optional datasource without always having to define it in the application context?
Don't use an "optional data source". Instead, always define the resource-ref, and add an env-entry:
#Resource(name="useDataSource")
private boolean useDataSource;
...or corresponding XML:
<env-entry>
<env-entry-name>useDataSource</env-entry-name>
<env-entry-type>java.lang.Boolean</env-entry-type>
<env-entry-value>false</env-entry-value>
</env-entry>
The value of the env-entry can be changed at deployment time.

Categories

Resources