Why doesn't Websphere 9 detect Annotated mappedName value for EJBs? - java

Following is my Sample Code:
AddStatelessBean.java:
#Stateless(name = "AddStatelessBean", mappedName="ASBean")
#Remote(AddStatelessBean.class)
#LocalBean
public class AddStatelessBeanImpl implements AddStatelessBean {
public int add(int a, int b) {
return a + b;
}
}
My Calling Code:
CallAddBean.java:
public static AddStatelessBean getAsbByName() throws Exception {
Context initialContext = new InitialContext();
AddStatelessBean asbObj = (AddStatelessBean) initialContext.lookup("ASBean");
return asbObj;
}
But I get the following error:
javax.naming.NameNotFoundException: Context: VRDWIN7WAS9Node03Cell/nodes/VRDWIN7WAS9Node03/servers/server1, name: ASBean: First component in name ASBean not found. [Root exception is org.omg.CosNaming.NamingContextPackage.NotFound: IDL:omg.org/CosNaming/NamingContext/NotFound:1.0]
BUT, if I go to Websphere Admin Console -> Applications -> Websphere Enterprise Applications -> -> EJB JNDI Names and assign the same JNDI name there and try to lookup, it is working.
I don't want to do that extra step or configure any XMLs (ibm-ejb-jar-bnd.xml) for making that happen during App Deployment itself.
How do I make this binding from pure JAVA Code itself? My main motive is to make my code run Server independent.

Related

JNDI in Stateless Bean not found in Wildfly 10

I am using wildfly 10.
For some reason I've got error like this:
javax.naming.NameNotFoundException: ServiceAImpl-- service jboss.naming.context.java.global.ServiceAImpl: javax.naming.NameNotFoundException: ServiceAImpl -- service
The way that I access to jndi:
InitialContext initialContext = new InitialContext();
Context context = (Context) initialContext.lookup("java:global/");
IWorker worker = (IWorker) context.lookup("ServiceAImpl");
worker.createTimer(task);
rest of code:
public interface IWorker{
void createTimer(ExecutableTask aExecutableTask);
}
#Stateless
#Local(IServiceA.class)
public class IServiceAImpl
implements IServiceA {
#Override
public void createTimer(ExecutableTask aExecutableTask) {
System.out.println("I am doing some jobs");
}
}
#Local
public interface IServiceAextends IWorker{
}
How can I get access to this IWorker? How to get this JNDI?
Take a look here. You are going to find something similar to this in your Wildfly logs when it is starting.
java:global/<your-project>/bus-facade-fumo/WUFFacade!<your-project>.wuf.WUFFacadeRemote
java:app/bus-facade-<your-project>/WUFFacade!<your-project>.wuf.WUFFacadeRemote
java:module/WUFFacade!<your-project>.wuf.WUFFacadeRemote
java:jboss/exported/<your-project>/bus-facade-<your-project>/WUFFacade!<your-project>.wuf.WUFFacadeRemote
java:global/<your-project>/bus-facade-<your-project>/WUFFacade
java:app/bus-facade-<your-project>/WUFFacade
java:module/WUFFacade
So you can find the JNDIs you need in your console logs, just like the example above. In you case, you are almost there, but you have to complete this piece of code with the complete information:
Context context = (Context) initialContext.lookup("java:global/<HereYouNeedMoreInformation>");

JAVA Lookup Failed for bean name in SerialContext

The Scenario goes as follows :
i'm coding a java enterprise application
first i created entity classes from database table "Derby" then i made a helper classes in a java library project then i created a session bean in the enterprise application bean and created a bean facade remote in the java library project
here is the important code part of the session bean :
#Stateless(mappedName = "officefacade")
public class OfficeFacade implements OwnerFacadeRemote {
#PersistenceContext
private EntityManager em;
and then i coded a simple client to test the methods
client code :
public class Client {
private OwnerFacadeRemote request;
public static void main(String[] args) {
// TODO code application logic here
Client x = new Client();
}
public Object getEJBBean(String beanName)
{
try
{
InitialContext ctx = new InitialContext();
return ctx.lookup(beanName);
}
catch(Exception ex)
{
System.err.println("Error : " + ex.getMessage() + "\n\n\n");
}
return null;
}
private void insert()
{
request.createOwner(new OwnerDetails("1","M","444","M","afcdv"));
}
private void display()
{
List<OwnerDetails> xx = request.getAllOwner();
}
public Client()
{
request = (OwnerFacadeRemote) getEJBBean("officefacade");
insert();
display();
}
the problem is every time i run the client i get the error that Lookup failed for 'officefacade'
here is the complete error text
> Error : Lookup failed for 'officefacade' in SerialContext[myEnv{java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFac tory, java.naming.factory.url.pkgs=com.sun.enterprise.naming, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl}
how to make sure the mapped name is being available and how to fix it so the it can be found by the lookup even if it means hard coding the mapped name in the serial context "i don't know what this is but it seem as the problem is coming from it"
any help is much appreciated and thanks in advance for your efforts and i'm pretty sure everything is implemented correctly so it's a mapped name related problem
tools of development is netbeans 8.0.2 and glassfish 4.1
Try to replace #Stateless(mappedName = "officefacade") with #Stateless(name = "officefacade"), the lookup method of the InitialContext seems to work with the bean name
See the related JavaDoc section and the related method for more details
UPDATE
Just checked Oracle's documentation on this topic - according to the information available there you might need to actually lookup for "java:module/officefacade" instead of pure "officefacade", depending on the bean context.

How to look up an object of a class

There is an application ABC which dependency is on an ejb module 'XYZ' but both are deployed & running on different server machine.
ABC deployed on JBoss AS & IP address is 192.108.1.1
XYZ deployed on JBOss As & IP address is 192.108.1.2
in XYZ ejb module, there is a xyzService class which access db and populates the data into a bean class, please see below
#Stateless(mappedName = "ejb/xyzService")
#TransactionManagement(TransactionManagementType.BEAN)
public class XyzService extends XyzPersistenceService implements xyzRemote, xyzLocal {
public List<xyzBean> fetchDataFromDB (List<String> idList) throws Exception
{
List<xyzBean> detailList = null;
try {
// gets data from DB and populate into a bean class i.e. xyzBean
} catch (Exception e) {
new myExceptionClass("error", e);
}
return detailList;
}
}
//Bean class
public class xyzBean{
String Id;
String name;
// getter-setter here
}
Now i want,
1. lookup the object of service class of XYZ module
2. invoke the method
3. gets the list of bean class
Could you please guide me how to do that, while i am bit confused how to start doing this from my ABC application ?
This example is geared towards connecting to the XYZ bean, but you could easily use it with a little adjustment for the ABC bean. Anyway, here is how you can lookup your xyzService.
Explicitly
By #EJB annotation
By ejb-ref
Explicitly
// Lookup the EJB from JNDI
InitialContext ctx = new InitialContext();
xyzRemote remoteobj = (xyzRemote)ctx.lookup("ejb/xyzService");
By annotation
#EJB (mappedName="ejb/xyzService")
private xyzRemote remoteobj;
With annotation the container injects an instance of the remote EJB bean through DI.
By ejb-ref
In your client class, add the below code. This is only a
InitialContext ctx = new InitialContext();
xyzRemote remoteobj = (xyzRemote) ctx.lookup("java:comp/env/ejb/xyzService");
As for configuring your client's InitialContext, you'll need a jndi.properties file
### JBossNS properties
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://192.108.1.2:1099
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces

Access Config.groovy from Java class

When my Grails app starts up, I also begin a Spring Integration and Batch process in the background. I want to have some DB connection properties stored in the Config.groovy file, but how do I access them from a Java class used in teh Integration/Batch process?
I found this thread:
Converting Java -> Grails ... How do I load these properties?
Which suggests using:
private Map config = ConfigurationHolder.getFlatConfig();
followed by something like:
String driver = (String) config.get("jdbc.driver");
This actually works fine (teh properties are loaded correctly from Config.groovy) but the problem is that ConfigurationHolder is after being deprecated. And any thread I've found dealing with the issue seems to be Grails-specific and suggest using dependancy injection, like in this thread:
How to access Grails configuration in Grails 2.0?
So is there a non-deprecated way to get access to the Config.groovy properties from a Java class file?
Just checked in some of my existing code, and I use this method described by Burt Beckwith
Create a new file: src/groovy/ctx/ApplicationContextHolder.groovy
package ctx
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationContextAware
import javax.servlet.ServletContext
import org.codehaus.groovy.grails.commons.GrailsApplication
import org.codehaus.groovy.grails.plugins.GrailsPluginManager
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationContextAware
#Singleton
class ApplicationContextHolder implements ApplicationContextAware {
private ApplicationContext ctx
private static final Map<String, Object> TEST_BEANS = [:]
void setApplicationContext(ApplicationContext applicationContext) {
ctx = applicationContext
}
static ApplicationContext getApplicationContext() {
getInstance().ctx
}
static Object getBean(String name) {
TEST_BEANS[name] ?: getApplicationContext().getBean(name)
}
static GrailsApplication getGrailsApplication() {
getBean('grailsApplication')
}
static ConfigObject getConfig() {
getGrailsApplication().config
}
static ServletContext getServletContext() {
getBean('servletContext')
}
static GrailsPluginManager getPluginManager() {
getBean('pluginManager')
}
// For testing
static void registerTestBean(String name, bean) {
TEST_BEANS[name] = bean
}
// For testing
static void unregisterTestBeans() {
TEST_BEANS.clear()
}
}
Then, edit grails-app/config/spring/resources.groovy to include:
applicationContextHolder(ctx.ApplicationContextHolder) { bean ->
bean.factoryMethod = 'getInstance'
}
Then, in your files inside src/java or src/groovy, you can call:
GrailsApplication app = ApplicationContextHolder.getGrailsApplication() ;
ConfigObject config = app.getConfig() ;
Just to register, in Grails 2.x, there's a Holders class that replaces this deprecated holder. You can use this to access grailsApplication in a static context.
I can't work out why this is not working, but I can suggest an alternative approach entirely. Grails sets up a PropertyPlaceholderConfigurer that takes its values from the grailsApplication.config, so you could declare a
public void setDriver(String driver) { ... }
on your class and then say
<bean class="com.example.MyClass" id="exampleBean">
<property name="driver" value="${jdbc.driver}" />
</bean>
This also works in resources.groovy if you're using the beans DSL, but you must remember to use single quotes rather than double:
exampleBean(MyClass) {
driver = '${jdbc.driver}'
}
Using "${jdbc.driver}" doesn't work because that gets interpreted by Groovy as a GString and (fails to be) resolved when resources.groovy is processed, whereas what you need is to put a literal ${...} expression in as the property value to be resolved later by the placeholder configurer.

EJB Factory Class

I'm trying to create an EJB factory class, which works like this: You have a method which takes as argument a class of an EJB, then it checks whether the EJB has a remote interface (if not throw an exception) and if it does, it returns the concerning EJB.
The code below does exactly this. However the object it returns is of the type of the remote interface of the concerning bean and not of the bean itself. How can I change this? Is there a way to tell Java that the generic type T is of the same type as the class passed to the methods.
import java.util.Properties;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.naming.*;
public class EJBFactory
{
private InitialContext ctx;
public EJBFactory() throws NamingException {
ctx = new InitialContext();
}
public EJBFactory(String host, String port) throws NamingException {
Properties props = new Properties();
props.setProperty("org.omg.CORBA.ORBInitialHost", host);
props.setProperty("org.omg.CORBA.ORBInitialPort", port);
ctx = new InitialContext(props);
}
.
// To improve: The object returned should be of the type ejbClass
// instead of the remote interface, which it implements
public <T> T createEJB(Class ejbClass) throws NamingException
{
Class remoteInterface = null;
for(Class interface_: ejbClass.getInterfaces()) {
if(interface_.isAnnotationPresent(Remote.class))
remoteInterface = interface_;
}
if(remoteInterface == null)
throw new IllegalArgumentException(
"EJB Requires a remote interface");
// Get the stateless annotation, then get the jndiName
Stateless stateless =
(Stateless)ejbClass.getAnnotation(Stateless.class);
String jndiName = stateless.mappedName();
T ejbObj = (T) ctx.lookup(jndiName);
return ejbObj;
}
}
Example of a unit test which uses the Factory.
import junit.framework.TestCase;
public class SimpleEJBTest extends TestCase
{
TestRemote testBean;
#Override
protected void setUp() throws Exception {
super.setUp();
EJBFactory ejbFactory = new EJBFactory();
testBean = ejbFactory.createEJB(TestBean.class);
}
public void testSayHello() {
assertEquals("Hello", testBean.sayHello());
}
}
Note: The example works with Glassfish, I didn't test it with any other app server.
Clients of EJBs interact with them through the local/ remote interface that the EJBs implement. Client applications never have direct access to an actual session bean class instance. This is done to make instance pooling possible, where the container can reuse EJB instances to service different requests.
I'm not sure why you need to access the actual bean's object (since obviously I dont know your requirement). But if you still need to create an instance of that you can do it as follows using reflection Class.forName(className).newInstance(); Again the instance that you create like this is not an EJB. It is just a POJO thats all.
EDIT - after your comment regarding junit testing: When you access business methods from a JavaSE as follows, you are actually calling the methods in the EJB - just that you interact thru the interface. So if you want to test any business methods you can still do it from an object got thru a JNDI lookup in a Junit test.
//MyGreatBean implements MyGreat. MyGreat has #Remote, MyGreatBean has #Stateless
ref = jndiContext.lookup("MyGreatBean/remote");
MyGreat bean = (MyGreat) ref;
String retValue = bean.businessMethod();
assertEquals("Success", retValue);
From an earlier comment, I get a feeling you want to check what kind of annotations have been added to the actual EJB class - if you want to do that kind of checking without actually running the business methods, you can create an instance using Class.forName... like I mentioned above. When you create an instance like this you can only call methods that don't do any "Java EE" stuff. For example you can call a method in the EJB class that is as follows
public String someMethod(){
return "I am a POJO but I look like an EJB";
}
I do not think that you can get the EJB object. You can only get the interface. The createEJB should be called with the interface and it returns the interface.
try replacing
public <T> T createEJB(Class ejbClass) throws NamingException
with
public <T> T createEJB(Class<T> ejbClass) throws NamingException
Can you try this?
Create a interface. Make it have #Remote. Your ejb that is annotated with #Stateless should implement the above created interface. Now try to do the same thing that you are doing I think it should give you the desired result. Typing it down here without copying from an ide so excuse any errors. But you should get the drift I guess.
#Remote
public interface Example{
String some();
}
#stateless
public class ExampleBean implements Example{
}

Categories