Java EE using Datasource without lookup method - java

I'm trying to use a Datasource (Database) in my program using JNDI. I got it to work partially but not like I want it to work.
I want to inject the JNDI Resource, but it does not work properly.
It does not work, if I use the annotation.
#Resource(name="jdbc/crmv1")
DataSource ds;
But it does work, when I use the lookup method:
try {
ds = InitialContext.doLookup("jdbc/crmv1");
} catch (NamingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
I want to use the annotation. I'm pretty sure, that I have to set something in the web.xml, but I don't know what. I tried to google it, but I'm not really sure what searchterms to use.

Using the Resource annotation you can try using the lookup element instead of the name and use the jndi-name you configured in your application server.
Example-
If it is mapped with the jndi-name "jdbc/crmv1" try #Resource(lookup="dbc/crmv1") or #Resource(lookup="java:jdbc/crmv1")
The only relation to the web.xml is that you use a deployment descriptor to override the resource mapping that you specify in an annotation.

Related

EJB 2.1 to EJB 3.1 Migration - Session EJB with name not found

I am migrating Ejb 2.1 to Ejb 3.1. I changed Java Version from 1.6 to 1.8, and Ejb Version from 2.1 to 3.1. Once I made the changes, I am getting problems in the ibm-ejb-jar-bnd.xml and ibm-ejb-jar-ext.xml files.
I am getting these messages:
1: Session EJB with name 'abcEJB' not found
2: Resource reference with name 'ResourceRef_xyz' not found for this EJB or interceptor
Am I missing anything?
I have migrated from EJB 2.1 to EJB 3.1 couple of years back and I recall facing the same issues and error you are facing.
Although I don't remember the exact action that fixed the issue nor other issues I faced along the way, but I will tell you what I did to fix ALL issues, including this one.
Note: It's not an easy task to migrate, but following these next steps as described will save you lots of hassle later on.
Annotate session beans and interfaces with proper annotations:
In my case I had remote interfaces for EJB 2.1 beans. Since I did not need an actual remote interface in my application, I switched them into local interfaces.
Empty ibm-ejb-jar-bnd.xml and ibm-ejb-jar-ext.xml
Change clients to lookup either using DI, JNDI name. In my case I used JNDI lookup.
Now the code should look like this:
Session Bean interface:
#Local
public interface MySessionInterface {
// TODO :: declare business methods
}
Session bean implementation:
#stateless
public interface MySessionBeanImpl implements MySessionInterface {
// TODO :: implement business methods
}
Service Locator to lookup EJBs using JNDI:
public class ServiceLocator {
public final <T> T getLocalSession(Class<T> _class) throws NamingException {
return (T) new InitialContext().lookup("ejblocal:" + _class.getName());
}
}
Client:
public class SessionClient {
public void performOperation() {
try {
MySessionInterface session = ServiceLocator.getLocalSession(MySessionInterface.class);
// TODO :: perform business logic here
} catch (NamingException e) {
// TODO :: handle exception
}
}
}
Of course service locator can have the following improvements but I removed them for brevity:
Cache the result instead of looking it up everytime from the JNDI
Catch the checked exception NamingException and throw your own runtime exception
Hope you find it useful.
In both the ibm-ejb-jar-bnd.xml and ibm-ejb-jar-ext.xml files, the <session> element must contain the name of the EJB that it applies to. That name must match the name of an EJB defined in the corresponding ejb-jar.xml file, specifically the <ejb-name> element, or the name of the EJB identified by either the #Stateless, #Stateful, or #Singleton annotation. When using annotations, the name refers to either the name attribute of the annotation, or the simple class name.
Similarly, the <resource-ref> element must contain the name of the resource references that it applies to. In ejb-jar.xml, this would be the <res-ref-name> element. If the resource reference is defined via annotations, then the name element of the #Resource annotation, or the default name if not specified.

Different value of JNDI parameter for different standalone instances in GlassFish

I need to have the same application deployed in GlassFish several times, with different JNDI parameters, but I can't find a way to do that.
I know I can have different standalone instances and apply the different JNDI resources to one or several instances, but I can't have the same resource name with different values for the different instances.
What is the way to achieve what I need?
To achieve the requirement, you can use different JNDI configurations in a property file and pass the values in JVM arguments to apply each configuration to several glassfish server instances.
So in the end what I did is to use this:
#Resource(lookup = "java:app/AppName")
private String appName;
private String myJndiParameter;
And then since I can't use a variable to get the custom jndi parameter in an annotation, I created a #PostConstruct method, where I get the jndi value that I want, something like this:
#PostConstruct
public void initialize ()
{
try
{
myJndiParameter = (String) new javax.naming.InitialContext().lookup(appName + "/" + "my.jndi.parameter.name");
} catch (NamingException e)
{
// Treat exception
}
}
In GlassFish, my custom resource name looks like:
myapp/my.jndi.parameter.name
I'm open to suggestions to improve it :)

Inject stateful EJB beans in a maven project

I don't understand one thing that I hope someone of you could explain me. I have a maven enterprise project developed with glassfish.
I use the insert code netbeans function (right click) to call bean in a servlet and in particular the annotation
#EJB
I don't understand why when I call a stateful session bean through Insert Code function in netbeans the bean is called through JNDI. Here what I mean
private BookingBeanInterface lookupBookingBeanLocal() {
try {
Context c = new InitialContext();
return (BookingBeanInterface) c.lookup("java:global/it.volaconnoi_volaconnoi-webapp-ear_ear_1.0-SNAPSHOT/it.volaconnoi_volaconnoi-webapp-ejb_ejb_1.0-SNAPSHOT/BookingBean!it.volaconnoi.logic.BookingBeanInterface");
} catch (NamingException ne) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, "exception caught", ne);
throw new RuntimeException(ne);
}
}`
The above function hasn't been wrote by me
I can't inject a stateful session bean through EJB?
Here is the solution to the problem:
As you probably already know a single Servlet instance is used to handle multiple requests from multiple clients so the Stateful EJB should not be injected directly in the Servlet and kept as an instance property, or we will face obvious thread-safety related issues. In our case we are fetching it from JNDI inside doGet method and storing it in the HTTP session so each user will have it's own Sateful EJB instance.

How to connect junit and tomcat in java?

I have configured MysqlDataSource in tomcat using this link.I have written junit test cases.when am i calling below connection from junit it throws following errors.
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
I have used following code
class DataConnection {
private static DataSource dataSource;
public DataConnection() {
try {
Context ctx = new InitialContext();
dataSource = (DataSource)ctx.lookup("java:comp/env/jdbc/test");
} catch (NamingException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
new DataConnection();
Connection con=dataSource.getConnection();
return con;
}
}
How to call tomcat from junit? How to achieve this?
The code you give gets the database connection from JNDI, e.g. when running in tomcat from the container. However, for Unit Tests (assuming that's what you use JUnit for) I'd rather suggest to use "dependency injection" - e.g. explicitly pass a database connection to the code under test or manually set it up before the test runs.
There's no need to rely on JNDI for executing your tests: That's not what you want to test, instead, you want to just verify that your actual code is running correctly.
You don't need any fancy library (e.g. spring) for dependency injection, just a slightly adjusted architecture. This will greatly enhance the testability of your application and lower the execution time of your tests.
(This is based on my assumptions of your situation based on the little bit of information that you give in your question)
Give TomcatJNDI a try. It is based on embedded Tomcat but initializes only Tomcat's JNDI environment without starting a server. So you can access all your resources as configured in Tomcat's configuration files in tests or from within any Java SE application. The API is simple. For instance to get a DataSource declared in context.xml:
TomcatJNDI tomcatJNDI = new TomcatJNDI();
tomcatJNDI.processContextXml(contextXmlFile);
tomcatJNDI.start();
Then you can lookup the DataSource as usual
DataSource ds = (DataSource) InitialContext.doLookup("java:comp/env/path/to/datasource")
More information about TomcatJNDI can be found here.

Initial Context property values for EJB lookup

I am learning basics of EJB 3.0. I have managed to get a sample code up and running. Now I am doing a line by line analysis to have in-depth knowledge. But I am stuck at few lines where there is a lookup to find the required bean.
Can anyone please explain me in simple language the meaning and the need of the following lines?
Properties properties = new Properties();
properties.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
properties.put("java.naming.factory.url.pkgs", "org.jboss.naming rg.jnp.interfaces");
properties.setProperty(Context.PROVIDER_URL, "localhost:1099");
IniialContext context = null;
SamleEjbRemote cl = null;
try {
context = new InitialContext(properties);
cl = (SampleEjbRemote) context.lookup("SampleEjbBean/remote");
} catch (NamingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
What is the exact meaning of each of the 'key' and 'value' that is used in properties?
Rest of it is to put the 'properties' in the initial context instance. I have had a very vague idea of the above, but I want to clarify it very clearly. I would be glad if anyone could point me to any links or insights about the above lines.
Thanks in advance.
Both properties configures JBoss JNDI HTTP InitialContext Factory Implementation
Official document here : http://docs.jboss.org/jbossas/jboss4guide/r1/html/ch3.chapter.html
See chapter 3.2.1.2. The HTTP InitialContext Factory Implementation
java.naming.factory.initial: The name of the environment property for specifying the initial context factory, which must be org.jboss.naming.HttpNamingContextFactory.
java.naming.factory.url.pkgs: For all JBoss JNDI provider this must be org.jboss.naming:org.jnp.interfaces. This property is essential for locating the jnp: and java: URL context factories of the JBoss JNDI provider.
UPDATE:
I would recommend to use jndi.properties file in your class path
### JBossNS properties
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://localhost:1099
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces

Categories

Resources