JNDI lookup on TomEE - ejb

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");

Related

lookup to EJBHome from Outside the container via Standalone applicatiion failed

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.

Using aquillian to test jax-rs - do I need a servlet?

I'm testing my jax-rs services using aquillian and the wildfly embeded container. In this setup, I'm trying to understand how my web services are handled by the server. To set things up, I have the following deployment in my test:
#Deployment
public static WebArchive create() {
return ShrinkWrap.create(WebArchive.class, "rest-service.war")
.addClasses(ProfileService.class,
Profile.class); // classes and other resources into the war
}
So that war gets deployed and its running in an embedable container. However, my test can't find a service at any of the URLs mapped in ProfileService. Is it because my war is missing a servlet? Specifically, a javax.ws.rs.core.Application instance? Or am I misunderstanding how EJB containers expose jax-rs services.
It is because you're missing a class that extends Application, however you don't need to register it as a servlet. As long as its annotated #ApplicationPath it will be picked up by the container.

Cannot reach EJB exposed as REST service

I'm trying to expose some EJBs as REST web service using JAX-RS annotations. When I deploy war file containing EJB Jar in WEB-INF/lib to Wildfly 8, I can see in web admin panel EJB Jar as deployed, But I cannot reach REST endpoints and get 404.
This is content of web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/separated/*</url-pattern>
</servlet-mapping>
</web-app>
This is a sample session bean I'm trying to serve as web service and put in jar file:
#Stateless(name = "TestSessionEJB")
#LocalBean
public class TestSessionBean {
#PersistenceContext(unitName = "TestPU")
private EntityManager em;
public AuthenticationSessionBean() {
}
#GET
#Path("ep")
public String testEP() {
return "Hello from testEP()";
}
}
I cannot reach testEP through /<war_file_name>/separated/ep. Added ejb-jar.xml descriptor to WEB-INF/, still no success. I made another service with classes compiled and deployed directly in war file's WEB-INF/classes:
#ApplicationPath("/integrated")
public class TestRestApp extends Application {
}
#Path("/ep")
public class TestRestEp {
#GET
public String doGet() {
return "success";
}
}
Here I can reach doGet() through /<war_file_name>/integrated/ep.
Am I missing something? Can I deploy EJBs as separated jar files and expose them as REST web services with no wrapper?
UPDATE:
I annotated TestSessionBean with ApplicationPath("separated") and made it extending from javax.ws.rs.Application. Still getting 404 but this time It's different; 404 without "Not Found" body. If I make an endpoint path same as an endpoint in TestRestApp, e.g #Path("ep") It maps to endpoint in TestRestApp and I get "success" instead of "Hello from testEP()" by navigating to /<war_file_name>/separated/ep. If I annotate a method in TestSessionBean with a path not defined in TestRestApp result is 404. I cleared my web.xml out of servlet definitions and still same result.
First
Simply annotating an EJB class's method with JAX-RS annotations will not make the method a JAX-RS resource method. You need to make TestSessionBean a root resource class by annotating it with #Path, like you did with TestRestEp. Or you can make this class a Sub-Resource and have a Root resource pass the request to this class. I'd just stick to the former, if you have no idea what the latter means.
Second
Keeping in mind Wildfly (JBoss) modular architceture
Stated in the Resteasy (Wildfly's JAX-RS implementation) Reference Guide:
Resteasy and JAX-RS are automically loaded into your deployment's classpath, if and only if you are deploying a JAX-RS Application.
That being said, your web.xml doesn't create a JAX-RS application. You are basically depending on the (default JAX-RS specified) javax.ws.rs.Application servlet, which is only loaded if the JAX-RS module is loaded into the Server.
When you have an Application subclass, with the #ApplicationPath annotation, this creates a JAX-RS application and the JAX-RS module is loaded into the Server and the classpath will be scanned for resource classes.
Also stated in the JAX-RS spec:
The resources and providers that make up a JAX-RS application are configured via an application-supplied subclass of Application. An implementation MAY provide alternate mechanisms for locating resource classes and providers (e.g. runtime class scanning) but use of Application is the only portable means of configuration.
So I would stick to the Application subclass. No web.xml needed

WCF Data Service as Library

Today I am digging into WCF Data Service and I have a question regarding this. Can I create WCF Data service as Library and just only create WCF data Service in our existing web app and take reference that library using Factory property so service will deploy with existing web application.
As I know We can create WCF Service Library and only need to take reference that library in Web application like :
Create a WCF Library and implement service contract
Create a Web application and add new item as Wcf service file then take reference WCF library
<%# ServiceHost Service="MyServiceLibrary.MyService" Factory="System.ServiceModel.Activation.WebServiceHostFactory" />
Instead of a service library, I want to create OData service library.
Thanks
Yes, you can host a WCF Data Service in your own assembly - with a few little tricks. I researched this a while ago and came up with these steps / instructions.
Here's how:
put your data model (EF Data Model) into its own assembly, let's call it DataModel
create a new class library project (call it MyDataServiceHost)
add a few references:
your DataModel assembly with the data layer
System.ServiceModel
System.ServiceModel.Web
System.Data.Services.Client
System.Data.Services - you cannot pick this from the usual Add Reference dialog under the .NET category - you need to browse for the assembly file. Find the directory C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0 (or C:\Program Files (x86)\... on a 64-bit machine) and pick the System.Data.Services.dll inside it
add a new class to that class library and call it e.g. YourDataService.cs - it will look something like this:
using System.Data.Services;
using System.Data.Services.Common;
using DataModel;
namespace MyDataServiceHost
{
public class YourDataService : DataService<YourModelEntities>
{
// This method is called only once to initialize service-wide policies.
public static void InitializeService(DataServiceConfiguration config)
{
// TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
// Examples:
config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
}
}
}
You can name the class anything you like, and it has to derive from DataService<T> where T is the name of your data model; if you're using Entity Framework, it's the name of your object context class - typically something like (database)Entities or whatever you picked when you created the EDM
add another class to your new project, call it MyDataServiceHost.cs and it will look something like this:
using System;
using System.Data.Services;
using DataModel;
namespace MyDataServiceHost
{
public class MyDataServiceHost
{
public static void LaunchDataService(string baseAddress)
{
Uri[] baseAddresses = new Uri[1];
baseAddresses[0] = new Uri(baseAddress);
using(DataServiceHost host = new DataServiceHost(typeof(YourDataService), baseAddresses))
{
host.Open();
Console.WriteLine("DataService up and running.....");
Console.ReadLine();
host.Close();
}
}
}
}
It instantiates a DataServiceHost, which is derived from WebServiceHost (which in turn is derived from ServiceHost) and it will spin up the WCF Data Service runtime for you.
now you can start up your WCF Data Service from any app using:
MyDataServiceHost.LaunchDataService("http://localhost:4444/YourService");
last thing to remember: the app that you use to launch the WCF Data Service must have the connection string (the EDM connection string, if you're using Entity Framework) in its app.config (or web.config) in order for this to work!

Using Blazeds To Connect to a EJB on Glassfish

The task is to try to connect directly to a stateless EJB deployed on Glassfish. I have already done this via Web Service and I can also connect to the EJB by calling a remote java object which uses JNDI to find and load the bean. What I cannot do is directly connect to the EJB with Blazeds. I am using EBJ3Factory BY Ryan Norris (downloaded from adobe site) as follows;
My WEB-INF/flex/services-config.xml has;
<factories>
<factory id="ejb3" class="com.adobe.ac.ejb.EJB3Factory" />
</factories>
My WEB-INF/flex/remoting-config.xml has;
<destination id="MyEJB">
<properties>
<factory>ejb3</factory>
<source>java:global/Together/PSearch!ejb.PSearch</source>
</properties>
</destination>
I have a simple java class that can access the bean so I can use Blazeds to call the class which then calls the bean;
public void getBean() {
PSearch search;
InitialContext ctx;
try {
ctx = new InitialContext();
search = (PSearch) ctx.lookup("java:global/Together/PSearch!ejb.PSearch");
System.out.println("jndi okay");
} catch (NamingException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
}
The asadmin command for the context in glassfish shows me;
./asadmin list-jndi-entries --context java:global/Together
PSearch__3_x_Internal_RemoteBusinessHome__: javax.naming.Reference
PSearch!ejb.PSearchRemote: javax.naming.Reference
PSearch!ejb.PSearch: com.sun.ejb.containers.JavaGlobalJndiNamingObjectProxy
PSearch!ejb.PSearchLocal: com.sun.ejb.containers.JavaGlobalJndiNamingObjectProxy
Yet when I use Eclipse / Flash Builder to try to Import a BlazeDS service I get an introspection error;
java:global/Together/PSearch/!ejb.PSearch is not available in the specified location
I have also tried changing the remoting-config.xml to point to local and remote interfaces but no joy!
Any pointers would be greatly appreciated.
One workaround you could do would be to remove the factory XML element, replace the source JNDI name with the EJB fully qualified class name and create the service with Flash Builder using the BlazeDS RTS service as you tried to do.
<destination id="MyEJB">
<properties>
<source>packagename.EJBClassName</source>
</properties>
</destination>
When you are done making the service client, service and the value objects(return type etc) in your Flex project then put everything back as they were:
<destination id="MyEJB">
<properties>
<factory>ejb3</factory>
<source>java:global/Together/PSearch!ejb.PSearch</source>
</properties>
</destination>
What u r going to do actually is to treat the EJB 3.x as a normal POJO for the introspection in order to create the AS3 classes and when u r done change the destination to an EJB3 destination by using the factory.
I am working on a way to make this steps unnecessary. If I have time to finish it I will let you know.

Resources