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.
Related
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.
I have tried to implement this many ways, but this is the way that makes the most sense to me, and I am still unable to return anything from my resource. I added the resource with the GlassFish admin GUI (essentially, i am trying to save username and passwords on the local server).
While I am getting a null pointer exception (NPE), please do not point me here, it doesn't help me at all. What is a NullPointerException, and how do I fix it?
Here are my supporting classes...
Creating the bean
#LocalBean
#Stateless
public class JndiProperties {
#Resource(name="jndiCreds")
private Properties properties;
public String getUser() {
return properties.getProperty("UserName");
}
public String getPass() {
return properties.getProperty("UserPass");
}
}
This is my bean manager:
#ManagedBean
#ViewScoped
public class GetCreds {
#Inject
private JndiProperties property;
public String getUserName(){
return property.getUser();
}
public String getPassword(){
return property.getPass();
}
}
And this is how I call them
GetCreds creds = new GetCreds();
String username = creds.getUserName();
String pass = creds.getPassword();
I named the resource jndiCreds and have the names UserName and UserPass with the values containing respective data.
Here is the view from the GlassFish GUI:
Have any idea WHY it won't return my requested information? I AM receiving an NPE when I try to call the resource when I call either function from getCreds.
Help would be appreciated; I am very stuck.
I decided to step away from trying to use a bean and just accessing it directly (although I am giving up some security here). I am trying to access the data in a contextual manner. BUT! I still can not do it! Here is my NEW supporting class:
public class JndiProperties {
public Properties getProperties(String jndiName) {
Properties properties = null;
try {
InitialContext context = new InitialContext();
properties = (Properties) context.lookup(jndiName);
context.close();
}
catch (NamingException e) {
return null;
}
return properties;
}
And this is how I grab the information:
JndiProperties creds = new JndiProperties();
String username = creds.getProperties("jndiCreds").getProperty("UserName");
String pass = creds.getProperties("jndiCreds").getProperty("UserPass");
String credentials = String.join(System.getProperty("line.separator"),
"user=" + username,
"password=" + pass);
System.out.print(credentials);
I am using the same resource shown above. I am STILL ending up with null pointer... ANY help would be greatly appreciated.Feel free to answer what was wrong with my bean implementation also.
I have figured it out!
What was happening is first, I was a complete idiot, and I was trying to test my program with JUnit (IT DOES NOT RUN ON THE SERVER!)
Since the program wasn't being run on GlassFish, it couldn't access the resource.
Secondly, (and most importantly) I was missing the appserver-rt.jar- very important.
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
All,
I'm trying to do some unit testing in some archaic java code (no interfaces, no abstraction, etc.)
This is a servlet that uses a ServletContext (which I'm assuming is set up by Tomcat) and it has database information is set up in the web.xml/context.xml file. Now, I've figured out how to make a Fake ServletContext, but the code has
InitialContext _ic = new InitialContext();
all over the place (so it isn't feasible to replace it). I need to find a way to make a default InitialContext() able to do the _ic.lookup(val) without throwing an exception.
I'm assuming there is some way that the context.xml is getting loaded, but how that magic works, I'm drawing a blank. Anyone have any ideas?
Take advantage of the fact that InitialContext uses an SPI to handle its creation. You can hook into its lifecycle by creating an implementation of javax.naming.spi.InitialContextFactory and passing that to your tests via the system property javax.naming.factory.initial (Context.INTITIAL_CONTEXT_FACTORY). It's simpler than it sounds.
Given this class:
public class UseInitialContext {
public UseInitialContext() {
try {
InitialContext ic = new InitialContext();
Object myObject = ic.lookup("myObject");
System.out.println(myObject);
} catch (NamingException e) {
e.printStackTrace();
}
}
}
And this impl of InitialContextFactory:
public class MyInitialContextFactory implements InitialContextFactory {
public Context getInitialContext(Hashtable<?, ?> arg0)
throws NamingException {
Context context = Mockito.mock(Context.class);
Mockito.when(context.lookup("myObject")).thenReturn("This is my object!!");
return context;
}
}
Creating an instance of UseInitialContext in a junit test with
-Djava.naming.initial.factory=initial.context.test.MyInitialContext
on the command line outputs This is my object!! (easy to set up in eclipse). I like Mockito for mocking and stubbing. I'd also recommend Micheal Feather's Working Effectively with Legacy Code if you deal with lots of legacy code. It's all about how to find seams in programs in order to isolate specific pieces for testing.
Here's my solution to setting up the Inintial Context for my unit tests. First I added the following test dependency to my project:
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>catalina</artifactId>
<version>6.0.33</version>
<scope>test</scope>
</dependency>
Then I created a static method with the following code:
public static void setupInitialContext() throws Exception {
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.naming.java.javaURLContextFactory");
System.setProperty(Context.URL_PKG_PREFIXES, "org.apache.naming");
InitialContext ic = new InitialContext();
ic.createSubcontext("jdbc");
PGSimpleDataSource ds = new PGSimpleDataSource();
ds.setDatabaseName("postgres");
ds.setUser("postgres");
ds.setPassword("admin");
ic.bind("jdbc/something", ds);
}
Finally in each of my test class I add an #BeforeClass method which calls setupInitialContext.
Try setting up the system variables before:
System.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.naming.java.javaURLContextFactory");
System.setProperty(Context.URL_PKG_PREFIXES,
"org.apache.naming");
InitialContext ic = new InitialContext();
If you are using JUnit, follow this doc: https://blogs.oracle.com/randystuph/entry/injecting_jndi_datasources_for_junit
You can use PowerMock to mock construction of the InitialContext and control its behavior. Constructor Mocking is documented here.
PowerMock tests can be quite messy and complicated, refactoring is normally a better option.
Today I've faced the same problem (we can't user PowerMock) and solved it this way:
Don't lookup in the constructor so when you invoke #InitMock on the object, the constructor doesn't require the context yet.
Create a method for retrieving the service bean when needed like "getService().serviceMethod(param, param ...)":
/* Class ApplicationResourceProvider */
/* We can mock this and set it up with InjectMocks */
InitialContext ic;
/* method hiding the lookup */
protected ApplicationService getService() throws NamingException {
if(ic == null)
ic = new InitialContext();
return (ApplicationService)ic.lookup("java:global/defaultApplicationLocal");
}
On the test, set it up:
#Mock
ApplicationService applicationServiceBean;
#Mock
InitialContext ic;
#InjectMocks
ApplicationResourceProvider arp;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
when(ic.lookup(anyString())).thenReturn(applicationServiceBean);
...
}
Have you considered mockito?
It's as easy as:
InitialContext ctx = mock(InitialContext.class);
By the way, should you choose to use mocks i would recommend reading this article as well: http://martinfowler.com/articles/mocksArentStubs.html
A poor man's standalone implementation using no external libraries:
public class myTestClass {
public static class TestContext extends InitialContext {
public TestContext() throws NamingException {
super(true /*prevents initialization*/);
}
static Object someExpectedValue = "the expected string or object instance";
/*override the method(s) called by the legacy program on _ic, check the parameter and return the wanted value */
public Object lookup(String name) throws NamingException {
return name != null && name.equals("theValueOfVal") ? someExpectedValue : null;
}
}
public static class TestInitialContextFactory implements InitialContextFactory {
public Context getInitialContext(Hashtable<?, ?> arg0) throws NamingException {
return new TestContext();
}
}
public static void main(String[] args) throws SQLException {
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "the.package.myTestClass$TestInitialContextFactory");
/*now call the legacy logic to be tested*/
...
You could use a switch in the override of the lookup method to return the expected value for each different val value passed to _ic.lookup(val) throughout the legacy program.
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{
}