lookup to EJBHome from Outside the container via Standalone applicatiion failed - ejb

I have an EJB application which is Deployed in WebSphere 8
I am trying to connect it from Standalone java program following way
public static void main (String[] args) throws Exception
{
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory");
props.put(javax.naming.Context.PROVIDER_URL, "iiop//localhost:2809");
Context ctx = new InitialContext(props);
Object o = ctx.lookup("MyAppHome");
}
But this is leading to below exception
javax.naming.NameNotFoundException: Name "MyAppHome" not found in context
"serverlocal:CELLROOT/SERVERROOT".
at com.ibm.ws.naming.ipbase.NameSpace.lookupInternal(NameSpace.java:1228)
Further looking into it I found following supporting link https://www.ibm.com/developerworks/community/forums/html/threadTopic?id=ac01caaf-d2aa-4f3f-93b3-6f3d4dec3e6b
Here the answerer suggested using fully qualified bean name
java:global/ProjectName/ModuleName/BeanName!FullyQualif‌​iedNameOfRemoteInterface or BeanName#FullyQualif‌​iedNameOfRemoteInterface.
If it's a correct fix. Where can I find the Project name, Module Name and Bean Name? I do have xmi files in the project. Thanks!

The easiest way to determine the JNDI name for an EJB in WebSphere is to look for the binding information in the server logs. The JNDI names associated with each EJB interface are logged using the message ID CNTR0167I. Fore example:
CNTR0167I: The server is binding the com.example.DatabaseBean interface of the DatabaseBean enterprise bean in the TestProject.war module of the TestProject application. The binding location is: java:global/TestProject/DatabaseBean!com.example.DatabaseBean
Notice in this example that there does not appear to be both a project name (i.e. application name) and module name, because this test project was a standalone WAR module with an EJB packaged in it. Project/Application name is only used for EAR files.
Also note that a CNTR0167I is logged for JNDI names in both the java:global and SERVERROOT name contexts. So, in the error scenario above, it could be that the EJB was bound to ejb/MyAppHome and not just MyAppHome, so you can also determine the correct SERVERROOT JNDI name from the CNTR0167I messages as well. Either JNDI name may be used to lookup an EJB.

Related

JNDI lookup on TomEE

Hi have a Web project and a EJB project running on the same TomEE sever.
I have deployed the EJB project in the apps folder of the TomEE server and can see the EJB's are starting when the server starts.
INFO: Jndi(name=DefaultRegistrationProcess) --> Ejb(deployment-id=DefaultRegistrationProcess)
Below is one of the #Stateless beans in the EJB project
#Stateless(name = "DefaultRegistrationProcess")
public class DefaultRegistrationProcess implements RegistrationProcess {
#Override
public void process(Registration registration) {
System.out.println("Hello from Default registration process!");
}
}
From the Web project I want to do a JNDI Lookup to the DefaultRegistrationProcess bean.
Packaging the EJB with the Web project via maven I can do the JNDI Lookup using the following code.
new InitialContext().lookup("java:module/DefaultRegistrationProcess");
When trying to do the same call when the EJB is deploy separately I get
Exception occured: Name "module/DefaultRegistrationProcess" not found.
I have looked through the http://tomee.apache.org/documentation.html site and tried some examples but I'm still getting the error.
How can I do a local JNDI Lookup from within the Web project to the EJB when it is deployed on the same TomEE server?
I had to add #Remote to my business interface which my DefaultRegistrationProcess class implement.
#Remote
public interface RegistrationProcess {
public void process(Registration registration);
}
After that I could make a JNDI lookup using the LocalInitialContextFactory property and the JNDI name of DefaultRegistrationProcessRemote.
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY,"org.apache.openejb.core.LocalInitialContextFactory");
new InitialContext(p).lookup("DefaultRegistrationProcessRemote");

How to configure Java Message Driven Beans and Websphere Activation specification without hardcoded JNDI Names?

We have a MDB listening to a Queue reading data and sending data to another Queue
#MessageDriven(
activationConfig = { #ActivationConfigProperty(
propertyName = "destinationType", propertyValue = "javax.jms.Queue"
) },
mappedName = "jms/dataQ")
public class DataMDB implements MessageListener {
#Resource(name="jms/dataQueueConnectionFactory")
private ConnectionFactory connectionfactory;
#Resource(name="jms/dataDestinationQ")
private Destination destination;
...
}
and an XML (ibm-ejb-jar-bnd.xml) with bean configuration
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar-bnd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://websphere.ibm.com/xml/ns/javaee"
xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-ejb-jar-bnd_1_0.xsd"
version="1.0">
<message-driven name="DataMDB">
<jca-adapter activation-spec-binding-name="eis/dataListenerMDB"
destination-binding-name="jms/dataQ" />
<resource-ref name="jms/dataQueueConnectionFactory"
binding-name="jms/dataQueueConnectionFactory" />
<resource-env-ref name="jms/dataDestinationQ"
binding-name="jms/dataDestinationQ" />
</message-driven>
</ejb-jar-bnd>
and Activation specification for this MDB on WebSphere
As I have seen the examples over Google, this is the typical example of MDB and WAS Activation setup.
We have a problem here as all the JNDI names seen here are hardcoded in Java code anotations as well as in the ibm-ejb-jar-bnd.xml file.
So is there a way that these JNDI names can be brought outside the EJB project, so we could build one project for all customers and customers are free to have their Standard JNDI Names.
Else we have to build different .ear for each customer and which is not ideal.
Thanks in advance people.
Any ideas are welcome.
All values defined in the ibm-ejb-jar-bnd.xml maps references to the actual JNDI names. This can be overridden for each of your customers during application installation (mapping references to JNDI names steps in the admin console), after application installation, or during installation using scripts.
The binding file (ibm-ejb-jar-bnd.xml) provides only 'default names', in case you dont want to change them during installation.

File not found in EAR packaging

Inside my .ear
-META-INF
-lib
-ejb-shared.jar
-ejb.jar
-com/ejb/... (classes)
-fileXml.xml (file I'm trying to access)
-web.war
Some description:
"ejbshared" contains some ejbs and JPA entities
"ejb" contains some ejbs and JPA entities and uses "ejb-shared" project
The problem is that I can't access fileXml.xml. Inside an EJB bean (of ejb.jar) I've done:
File f = new File("fileXml.xml");
System.out.println(f.exists()); // returns false!
I don't know why, but it seems that fileXml.xml is not in the classpath, althougth it's present in the .ear, or maybe I'm doing things in the wrong way!
Using new File("fileXml.xml") will reference a file in the current working directory of the application server JVM, not relative to your specific application. Try using:
URL url = getClass().getResource("/fileXml.xml");
boolean exists = url != null;
System.out.println(exists);
InputStream input = url.openStream();
// ... read and close input stream

Consuming a Web Service from a Class Library

Using Visual Studio I have a Class Library (C#) where I added a reference to a Service (more preciselly a Web Service).
The Web Service classes and interfaces where generated correctly, and I am trying to consume them using the following code (the web service receives an returns a string):
CallWS request = new CallWS();
request.input = "input string";
WSClient client = new WSClient();
CallWSResponse response = client.CallWS(request);
The last line originates the following exception:
Could not find default endpoint element that references contract 'WS_INTER' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.
How do I solve this?
You have to add an application configuration file and set up system.serviceModel section defining the address of a service.
You can certainly do that in code. Check this or MSDN for description

Using Freemarker with Restlet 2.0 in a Java EE server

I'm a bit confused with what is written in the documentation(s) for Freemarker and Restlet's freemarker extension.
Here's the situation: The restlet engine serves an HTML representation of a resource (e.g. www.mysite.com/{user}/updates). The resource returned for this URI is an HTML page containing all the updates, that is created with a freemarker template. This application is hosted on a Glassfish v3 server
Question(s):
The freemarker configuration should only be loaded once as per the freemarker documentation:
/* You should do this ONLY ONCE in the whole application life-cycle:Create and adjust the configuration */
Configuration cfg = new Configuration();
cfg.setDirectoryForTemplateLoading(
new File("/where/you/store/templates"));
cfg.setObjectWrapper(new DefaultObjectWrapper());
What is the best place to do this in a Java EE app? I am thinking of having it as context-param in web.xml and using a ServletContextListener - but I'm not sure how to go about doing that.
As per freemarker's documentation we could also add a freemarkerservlet and map .ftl url-patterns to it. But this is already mapped by a Restlet servlet (i.e., the url-pattern of "/"). So having another one for *.ftl doesn't make sense (or does it?)
So the question is basically about how best to integrate with the 'configuration' of Freemarker so that it happens only once and what is the 'entry-point' for that piece of code (who calls it). Has anyone successfully used Freemarker + restlet in a Java EE environment? Any ideas?
Thanks!
This was a tricky question - indeed. Required me to go through the implementation of the source files in org.restlet.ext.Freemarker package - Phew!
Here's how you can do it
If you need to create your OWN Configuration Object, set the 'templateLoader' to use and then have TemplateRepresentation 'work' on it for rendering:
Configuration cfg = new Configuration();
ContextTemplateLoader loader = new ContextTemplateLoader(getContext(),"war:///WEB-INF");
cfg.setTemplateLoader(loader);
TemplateRepresentation rep = null;
Mail mail = new Mail(); //The data object you wish to populate - example from Restlet itself
mail.setStatus("received");
mail.setSubject("Message to self");
mail.setContent("Doh!");
mail.setAccountRef(new Reference(getReference(), "..").getTargetRef()
.toString());
Map<String, Object> data = new HashMap<String, Object>();
data.put("status", mail.getStatus());
data.put("subject", mail.getSubject());
data.put("content", mail.getContent());
data.put("accountRef", mail.getAccountRef());
rep = new TemplateRepresentation("Mail.ftl", cfg, data, MediaType.TEXT_HTML);
return rep;
If you are happy with the default and wish to use a class loader based way of loading the templates
//Load the FreeMarker template
Representation mailFtl = new ClientResource(
LocalReference.createClapReference(getClass().getPackage())
+ "/Mail.ftl").get();
//Wraps the bean with a FreeMarker representation
return new TemplateRepresentation(mailFtl, mail, MediaType.TEXT_HTML);
If you want to initialize the Configuration Object once and set the template by calling the setServletContextForTemplateLoading(...) method on the configuration object. You could always do this in a ServletContextListener
public class Config implements ServletContextListener {
private static Configuration cfg = new Configuration();
#Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext sc = sce.getServletContext();
cfg.setServletContextForTemplateLoading(sc, "/WEB-INF");
}
public static Configuration getFMConfig()
{
return cfg;
}
}
And then call the static getFMConfig() and pass it to TemplateRepresentation as in 1
Things to note:
If you do get a protocol not supported Exception it'll be in case 2. Implies that the ServerResource doesn't know what protocol to use to access the file - It'll be the CLAP protocol of Restlet. You may have to set up the init-params for RestletServlet in the web.xml file and have CLAP as one of the param-values
The TemplateRepresentation has quite a few constructors - if you DON'T pass in a configuration object during instantiation (using another overloaded constructor), it will create a new Configuration() for you. So you don't have to do any configuration set up as in 2 (This may strike you as obvious but I assumed that you WOULD still need to set a configuration or it would 'pick it up from somewhere')
If you DO wish to have your OWN configuration setup you MUST pass it to one of the constructors
Have a look at the "war:///" string in the constructor of ContextTemplateLoader in 1. this is important No where is it mentioned what this baseUri reference should be, not even in the docs. I tried for quite a while before figuring it out that it should be "war:///" followed by the folder name where the templates are stored.
For case 2 you'll probably have to store the templates in the same package as the class file from where this code is accessed. If you see carefully you'll notice a LocalReference parameter as an argument to ClientResource saying that the resource is supposed to be locally present and thus you need to use the custom CLAP protocol (classLoader Access Protocol)
Personal Frustration point - why isn't all this even clarified in the documentation or ANYWHERE :)
Hope it helps someone who stumbles upon this post! Phew!

Resources