Injecting jms resource in servlet & best practice for MDB - servlets

using ejb 3.1, servlet 3.0 (glassfish server v3)
Scenario:
I have MDB that listen to jms messages and give processing to some other session bean (Stateless).
Servelet injecting jms resource.
Question 1: Why servlet can`t inject jms resources when they use static declaration ?
#Resource(mappedName = "jms/Tarturus")
private static ConnectionFactory connectionFactory;
#Resource(mappedName = "jms/StyxMDB")
private static Queue queue;
private Connection connection;
and
#PostConstruct
public void postConstruct() {
try {
connection = connectionFactory.createConnection();
} catch (JMSException e) {
e.printStackTrace();
}
}
#PreDestroy
public void preDestroy() {
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
The error that I get is :
[#|2010-05-03T15:18:17.118+0300|WARNING|glassfish3.0|javax.enterprise.system.container.web.com.sun.enterprise.web|_ThreadID=35;_ThreadName=Thread-1;|StandardWrapperValve[WorkerServlet]:
PWC1382: Allocate exception for
servlet WorkerServlet
com.sun.enterprise.container.common.spi.util.InjectionException:
Error creating managed object for
class
ua.co.rufous.server.services.WorkerServiceImpl
at
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.createManagedObject(InjectionManagerImpl.java:312)
at
com.sun.enterprise.web.WebContainer.createServletInstance(WebContainer.java:709)
at
com.sun.enterprise.web.WebModule.createServletInstance(WebModule.java:1937)
at
org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1252)
Caused by:
com.sun.enterprise.container.common.spi.util.InjectionException:
Exception attempting to inject
Unresolved Message-Destination-Ref
ua.co.rufous.server.services.WorkerServiceImpl/queue#java.lang.String#null
into class
ua.co.rufous.server.services.WorkerServiceImpl
at
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:614) at
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.inject(InjectionManagerImpl.java:384)
at
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:141)
at
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:127)
at
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.createManagedObject(InjectionManagerImpl.java:306)
... 27 more Caused by:
com.sun.enterprise.container.common.spi.util.InjectionException:
Illegal use of static field private
static javax.jms.Queue
ua.co.rufous.server.services.WorkerServiceImpl.queue
on class that only supports
instance-based injection at
com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:532) ... 31 more |#]
my MDB :
/**
* asadmin commands
* asadmin create-jms-resource --restype javax.jms.ConnectionFactory jms/Tarturus
* asadmin create-jms-resource --restype javax.jms.Queue jms/StyxMDB
* asadmin list-jms-resources
*/
#MessageDriven(mappedName = "jms/StyxMDB", activationConfig =
{
#ActivationConfigProperty(propertyName = "connectionFactoryJndiName", propertyValue = "jms/Tarturus"),
#ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
#ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
})
public class StyxMDB implements MessageListener {
#EJB
private ActivationProcessingLocal aProcessing;
public StyxMDB() {
}
public void onMessage(Message message) {
try {
TextMessage msg = (TextMessage) message;
String hash = msg.getText();
GluttonyLogger.getInstance().writeInfoLog("geted jms message hash = " + hash);
} catch (JMSException e) {
}
}
}
everything work good without static declaration:
#Resource(mappedName = "jms/Tarturus")
private ConnectionFactory connectionFactory;
#Resource(mappedName = "jms/StyxMDB")
private Queue queue;
private Connection connection;
Question 2:
what is the best practice for working with MDB : processing full request in onMessage() or calling another bean(Stateless bean in my case) in onMessage() method that would process it.
Processing including few calls to soap services, so the full processing time could be for a 3 seconds.
Thank you.

Answers:
1. You cannot inject a resource into a static field. Injection into member fields occurs during object construction, static fields are not part of the object (only part of the class). In addition EJBs and servlets are threaded objects so this could possibly be dangerous to do.
2. If splitting the processing up into multiple EJB(s) makes sense do it that way, otherwise processing in onMessage() is perfectly valid.
One additional suggestion that I can give, is that you should take a look at CDI which is a new addition to the EE 6 specification and provides rich dependency injection.
Are you using an MDB to perform asynchronous operations, Servlet 3.0 has some neat asynchronous capabilities. I suggest you watch the entire presentation if you are not familiar with Servlet 3.0.

Related

Flink Retrofit not Serializable Exception

I have a Flink Job reading events from a Kafka queue then calling another service if certain conditions are met.
I wanted to use Retrofit2 to call the REST endpoint of that service but I get a is not Serializable Exception. I have several Flat Maps connected to each other (in series) then calling the service happens in the last FlatMap. The exception I get:
Exception in thread "main"
org.apache.flink.api.common.InvalidProgramException: The
implementation of the RichFlatMapFunction is not serializable. The
object probably contains or references non serializable fields.
...
Caused by: java.io.NotSerializableException: retrofit2.Retrofit$1
...
The way I am initializing retrofit:
RetrofitClient.getClient(BASE_URL).create(NotificationService.class);
And the NotificationService interface
public interface NotificationService {
#PUT("/test")
Call<String> putNotification(#Body Notification notification);
}
The RetrofitClient class
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl) {
if (retrofit == null) {
retrofit = new Retrofit.Builder().baseUrl(baseUrl).addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
Put your Notification class code for more details, but looks like this answer helps
java.io.NotSerializableException with "$1" after class

Why Stateful and Stateless beans behave in opposite way?

I created Stateful, Stateless and singleton bean classes and trying to access them two different servlet. And running project on JBoss server.
When I access Stateful bean from each servlet two different bean object will be created and different states(data) are preserved for them. But stateless bean object is shared between both servlet. Singleton bean also behaves same way as stateless bean.
My question is why stateful and stateless bean behaves in opposite way? Is lifecycle of session bean is same as lifecycle of servlet?
FirstServlet.java
#WebServlet("/FirstServlet")
public class FirstServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
#EJB
StatelessBean statelessBean;
#EJB
StateFullBean statefulBean;
#EJB
SingletonBean singletonBean;
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String message = "Beans not injected.";
String beanType = request.getParameter("beanType");
if ("Stateless".equals(beanType)) {
if (statelessBean != null) {
message = statelessBean.getHits();
} else {
message = "Stateless bean not injected.";
}
}
if ("Stateful".equals(beanType)) {
if (statefulBean != null) {
message = statefulBean.getHits();
} else {
message = "Stateful bean not injected.";
}
}
if ("Singleton".equals(beanType)) {
if (singletonBean != null) {
message = singletonBean.getHits();
} else {
message = "Singleton bean not injected.";
}
}
response.setContentType("text/html");
response.getWriter().print("<h1>" + message + "</h1>");
}
}
Similarly, I created one more servlet DemoServlet.java.
StateFullBean.java
#Stateful
public class StateFullBean{
int hits=0;
public String getHits() {
hits++;
return "StateFullBean number of hits " + hits;
}
public StateFullBean() {
System.out.println("StateFullBean created.");
}
}
StatelessBean.java
#Stateless
public class StatelessBean{
int hits=0;
public String getHits() {
hits++;
return "StatelessBean number of hits " + hits;
}
public StatelessBean() {
System.out.println("StatelessBean created.");
}
}
SingletonBean.java
#Startup
#Singleton(name="SingletonBean")
public class SingletonBean {
int hits=0;
public SingletonBean() {
System.out.println("SingletonBean created.");
}
public String getHits() {
hits++;
return "Singleton bean number of hits " + hits;
}
}
Am I missed something in code?
Everything is behaving as specified.
A stateless EJB delegates the call further to currently available instance in the pool. Apparently there's only one which is not used concurrently (yet) and therefore all clients have the same chance to access the same instance in the pool. If you fire more HTTP requests concurrently on the servlet(s), then chances increase that there's no available instance anymore and the container will create a new instance in the pool.
A stateful EJB is tied to its client (in your case, the web servlet instance). In other words, each servlet has its own stateful EJB instance which is not shared elsewhere.
A singleton bean is application wide and shared across all clients. In other words, each servlet will share the same singleton EJB instance.
Do note that the terms "client" and "session" in EJB context are absolutely not the same as those in WAR context and this is where many starters fall over. The EJB client is not the webbrowser, but the instance of the class where the EJB is injected (in your case, the web servlet instance). The EJB session is not the HTTP session, but the EJB-client session.
See also:
#Inject stateless EJB contains data from previous request
Why Stateless session beans?
When using #EJB, does each managed bean get its own #EJB instance?

Accessing ServletContext and HttpSession in #OnMessage of a JSR-356 #ServerEndpoint

I need to get the ServletContext from inside a #ServerEndpoint in order to find Spring ApplicationContext and lookup for a Bean.
For the moment my best approach is to bind that bean in the JNDI naming context and lookup it in the Endpoint. Any better solution is welcome.
I'm also looking for a reasonable way to sync servlet's HttpSession with websocket's Session.
The servlet HttpSession is in JSR-356 available by HandshakeRequest#getHttpSession() which is in turn available when a handshake request is made right before #OnOpen of a #ServerEndpoint. The ServletContext is in turn just available via HttpSession#getServletContext(). That's two birds with one stone.
In order to capture the handshake request, implement a ServerEndpointConfig.Configurator and override the modifyHandshake() method. The HandshakeRequest is here available as method argument. You can put the HttpSession into EndpointConfig#getUserProperties(). The EndpointConfig is in turn available as method argument #OnOpen.
Here's a kickoff example of the ServerEndpointConfig.Configurator implementation:
public class ServletAwareConfig extends ServerEndpointConfig.Configurator {
#Override
public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {
HttpSession httpSession = (HttpSession) request.getHttpSession();
config.getUserProperties().put("httpSession", httpSession);
}
}
Here's how you can use it, note the configurator attribute of the #ServerEndpoint:
#ServerEndpoint(value="/your_socket", configurator=ServletAwareConfig.class)
public class YourSocket {
private EndpointConfig config;
#OnOpen
public void onOpen(Session websocketSession, EndpointConfig config) {
this.config = config;
}
#OnMessage
public void onMessage(String message) {
HttpSession httpSession = (HttpSession) config.getUserProperties().get("httpSession");
ServletContext servletContext = httpSession.getServletContext();
// ...
}
}
As a design hint, it's the best to keep your #ServerEndpoint fully free of servlet API dependencies. You'd in the modifyHandshake() implementation better immediately extract exactly that information (usually a mutable Javabean) you need from the servlet session or context and put them in the user properties map instead. If you don't do that, then you should keep in mind that a websocket session can live longer than the HTTP session. So when you still carry around HttpSession into the endpoint, then you may run into IllegalStateException when you try to access it while it's being expired.
In case you happen to have CDI (and perhaps JSF) at hands, you may get inspiration from the source code of OmniFaces <o:socket> (links are at very bottom of showcase).
See also:
Real time updates from database using JSF/Java EE
Notify only specific user(s) through WebSockets, when something is modified in the database
Updated code for BalusC's answer, the onOpen method needs to be decorated with #OnOpen. Then there is no need anymore to extend the Endpoint class:
#ServerEndpoint(value="/your_socket", configurator=ServletAwareConfig.class)
public class YourSocket {
private EndpointConfig config;
#OnOpen
public void onOpen(Session websocketSession, EndpointConfig config) {
this.config = config;
}
#OnMessage
public void onMessage(String message) {
HttpSession httpSession = (HttpSession) config.getUserProperties().get("httpSession");
ServletContext servletContext = httpSession.getServletContext();
// ...
}
}
I tried out BalusC's answer on Tomcat (Versions 7.0.56 and 8.0.14). On both containers, the modifyHandshake's request parameter does not contain a HttpSession (and thus no servletContext).
As I needed the servlet context only to access "global" variables (web-application global, that is), I just stored these variables in an ordinary static field of a holder class. This is inelegant, but it worked.
That ooks like a bug in this specific tomcat versions - has anyone out there also seen this?
Somtimes we can't get session with above ServletAwareConfig of BalusC, this is because that the session is still not created. since we are not seek for session but servletContext, in tomcat we can do as below:
public static class ServletAwareConfig extends ServerEndpointConfig.Configurator {
#Override
public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {
try {
Field reqfld = request.getClass().getDeclaredField("request");
reqfld.setAccessible(true);
HttpServletRequest req = (HttpServletRequest) reqfld.get(request);
ServletContext ctxt = req.getServletContext();
Map<String, Object> up = config.getUserProperties();
up.put("servletContext", ctxt);
} catch (NoSuchFieldException e) {
} catch (SecurityException e) {
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
}
}
if we want init session immediately, we can call request.getSession().
Ref: Websocket - httpSession returns null

Why can't I use #EJB with #Named?

I basically am trying to inject a #Stateless bean with a local interface into a class annotated with #Named! My understanding is that injection is only possible when the injection point is managed (makes perfect sense), so for example it wouldn't be possible to inject into a POJO but you could inject into a Servlet, a JSF managed or another EJB.
I would have thought that it would have been possible to subsequently use it with #Named! However I get a NullPointerException that specifically seems to imply that this in fact doesn't seem possible!?
My classes look like this (stripped for clarity);
#Named
public class EmailUtil {
// Logger-------------------------------------------------------------------
private static final Logger LOG = Logger.getLogger(EmailUtil.class.getName());
// Constructor--------------------------------------------------------------
public EmailUtil() {
}
// EJB----------------------------------------------------------------------
#EJB AuditDAO audit;
// Methods------------------------------------------------------------------
public void sendEmail(
String emailSender,
String emailRecipient,
String emailSubject,
String emailHtmlBody,
String emailTextBody) throws FailedEmailException {
... code removed for clarity ...
// Call Amazon SES to send the message
try {
new SES().getClient().sendEmail(request);
// Create an audit log of the event
audit.create("Email sent to " + emailSender);
} catch (AmazonClientException ace) {
LOG.log(Level.SEVERE, ace.getMessage(), ace);
throw new FailedEmailException();
} catch (Exception e) {
LOG.log(Level.SEVERE, e.getMessage(), e);
}
}
}
#Stateless
public class AuditDAOImpl implements AuditDAO {
// Logger-------------------------------------------------------------------
private static final Logger LOG = Logger.getLogger(AuditDAOImpl.class.getName());
// EntityManager------------------------------------------------------------
#PersistenceContext(unitName = "iConsultPU")
private EntityManager em;
#Override
public void create(String event) {
String subject;
try {
/*
* If the current subject has authenticated and created a session we
* want to register their ID. However it is possible that a subject
* does not have an ID so we want to set it to unknown.
*/
subject = SecurityUtils
.getSubject()
.getPrincipals()
.asList()
.get(1)
.toString();
} catch (Exception e) {
subject = "UNKNOWN";
}
Audit audit = new Audit();
audit.setUserId(subject);
audit.setEventTime(Calendar.getInstance());
audit.setEvent(event);
em.persist(audit);
}
}
#Local
public interface AuditDAO {
public void create(String event);
}
I've tried using #Inject as well but that doesn't seem to work either. Have I misunderstood the specification or just poorly implemented it?
You should be injecting your dependencies. So if your EmailUtil is being manually constructed, injection won't work. It needs to be container managed. So if you use a servlet, or any managed bean, you can #Inject it. CDI injection only works for managed objects.
You can do some additional work arounds, such as manually invoking it against a constructed instance. Take a look at this question for an example like that: Parallel webservices access in a Weld CDI environment
Do you have the beans.xml in the correct location? Injection for #Named (and other CDI beans) is handled by CDI, which isn't started unless you have the beans.xml file in the correct location (WEB-INF for war and META-INF for jar).

JBoss 7.1.1.Final - EJB Remote Call - java.lang.IllegalStateException: No EJB receiver available for handling

I do have 2 JBoss stanalon instance running. 1 act as Server and another 1 would client.
SERVER:
Remote Interface
package com.xyz.life.service.ejb;
import java.io.Serializable;
import java.rmi.RemoteException;
import javax.ejb.EJB;
import javax.ejb.Remote;
#Remote
public interface QuoteFacade extends Serializable{
public boolean isAlive() throws RemoteException;
}
EJB Impl
package com.xyz.life.common.component.ejb.services;
import java.rmi.RemoteException;
import javax.ejb.Remote;
import javax.ejb.Stateless;
#Stateless(mappedName = "QuoteFacadeEJB")
#Remote(QuoteFacade.class)
public class QuoteFacadeEJB extends CommonSessionBean implements QuoteFacade {
private static final long serialVersionUID = -8788783322280644881L;
#Override
public boolean isAlive() throws RemoteException {
return true;
}
}
server.log
16:40:25,012 INFO [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-4) JNDI bindings for session bean named QuoteFacadeEJB in deployment unit subdeployment "quote.jar" of deployment "quote.ear" are as follows:
java:global/quote/quote.jar/QuoteFacadeEJB!com.xyz.life.service.ejb.QuoteFacade
java:app/quote.jar/QuoteFacadeEJB!com.xyz.life.service.ejb.QuoteFacade
java:module/QuoteFacadeEJB!com.xyz.life.service.ejb.QuoteFacade
java:jboss/exported/quote/quote.jar/QuoteFacadeEJB!com.xyz.life.service.ejb.QuoteFacade
java:global/quote/quote.jar/QuoteFacadeEJB
java:app/quote.jar/QuoteFacadeEJB
java:module/QuoteFacadeEJB
Client
public void testClient() {
try {
Hashtable<String, Object> jndiProps = new Hashtable<String, Object>();
jndiProps.put(Context.URL_PKG_PREFIXES, JNDINames.JBOSS_CLIENT_NAMING_PREFIX);
jndiProps.put("jboss.naming.client.ejb.context", true);
Context ctx = new InitialContext(jndiProps);
String name = "ejb:global/quote/quote.jar/QuoteFacadeEJB!com.ge.life.annuity.service.ejb.QuoteFacade";
/*
"ejb:global/quote/quote.jar/QuoteFacadeEJB!com.ge.life.annuity.service.ejb.QuoteFacade",
"ejb:app/quote.jar/QuoteFacadeEJB!com.ge.life.annuity.service.ejb.QuoteFacade",
"ejb:jboss/exported/quote/quote.jar/QuoteFacadeEJB!com.ge.life.annuity.service.ejb.QuoteFacade"
*/
Object ref = ctx.lookup(name);
QuoteFacade quoteFacade = (QuoteFacade) ref;
LOGGER.debug("isAlive : " + quoteFacade.isAlive());
} catch (Exception e) {
LOGGER.error("Remote Client Exception : ", e);
}
}
No error/log on server side. Client side, it is failing with following error:
java.lang.IllegalStateException: No EJB receiver available for handling [appName:global,modulename:quote,distinctname:quote.jar] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext#200cae
at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:584)
at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:119)
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:181)
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:136)
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:121)
at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:104)
at $Proxy10.isAlive(Unknown Source)
I tried without using Properties file:
private static QuoteFacade connectToStatelessBean(String name) throws NamingException {
Properties jndiProperties = new Properties();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
jndiProperties.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
jndiProperties.put(javax.naming.Context.PROVIDER_URL, "remote://localhost:4447");
jndiProperties.put(javax.naming.Context.SECURITY_PRINCIPAL, "admin");
jndiProperties.put(javax.naming.Context.SECURITY_CREDENTIALS, "Pass1234");
final Context context = new InitialContext(jndiProperties);
return (QuoteFacade) context.lookup(name);
}
public static void testLocal() {
String[] JNDINAME1 = {
"ejb:global/quote/quote.jar/QuoteFacadeEJB!com.ge.life.annuity.service.ejb.QuoteFacade",
"ejb:app/quote.jar/QuoteFacadeEJB!com.ge.life.annuity.service.ejb.QuoteFacade",
"ejb:module/QuoteFacadeEJB!com.ge.life.annuity.service.ejb.QuoteFacade",
"ejb:jboss/exported/quote/quote.jar/QuoteFacadeEJB!com.ge.life.annuity.service.ejb.QuoteFacade",
"ejb:global/quote/quote.jar/QuoteFacadeEJB",
"ejb:app/quote.jar/QuoteFacadeEJB",
"ejb:module/QuoteFacadeEJB"
};
for(int i=0;i<JNDINAME1.length;i++){
try {
QuoteFacade test1 = connectToStatelessBean(JNDINAME1[i]);
LOGGER.error("DSLKAJDLAS : " + test1.isAlive());
} catch (Exception e) {
LOGGER.error("DSLKAJDLAS : " , e);
}
}
LOGGER.info("Done - SANSSAN!!!!!!!!");
}
This time, different exception :
14.01.2013 17:40:37.627 [ERROR] - EJBClient - DSLKAJDLAS :
javax.naming.NamingException: JBAS011843: Failed instantiate InitialContextFactory org.jboss.naming.remote.client.InitialContextFactory from classloader ModuleClassLoader for Module "deployment.quote.war:main" from Service Module Loader
at org.jboss.as.naming.InitialContextFactoryBuilder.createInitialContextFactory(InitialContextFactoryBuilder.java:64)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:681)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:307)
at javax.naming.InitialContext.init(InitialContext.java:242)
at javax.naming.InitialContext.><init>(InitialContext.java:216)
at com.xyz.life.test.EJBClient.connectToStatelessBean(EJBClient.java:208)
at com.xyz.life.test.EJBClient.testLocal(EJBClient.java:225)
at com.xyz.life.test.EJBClient.test(EJBClient.java:172)
at com.xyz.life.common.web.struts.plugin.FrameworkStartupPlugIn.init(FrameworkStartupPlugIn.java:99)
at org.apache.struts.action.ActionServlet.initModulePlugIns(ActionServlet.java:1158)
at org.apache.struts.action.ActionServlet.init(ActionServlet.java:473)
at javax.servlet.GenericServlet.init(GenericServlet.java:242)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1202)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1102)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:3655)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:3873)
at org.jboss.as.web.deployment.WebDeploymentService.start(WebDeploymentService.java:90)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Try removing "global" from name:
String name =
"ejb:quote/quote.jar/QuoteFacadeEJB!com.xyz.life.service.ejb.QuoteFacade"
Also, your package name should be com.xyz.life.service.ejb (as seen on server log) and not com.ge.life.annuity.service.ejb.
Anyway, using remote-naming project for remote EJB invocations is discouraged as explained here.
... . So as you can see, we have managed to optimize certain operations by using the EJB client API for EJB lookup/invocation as against using the remote-naming project. There are other EJB client API implementation details (and probably more might be added) which are superior when it is used for remote EJB invocations in client applications as against remote-naming project which doesn't have the intelligence to carry out such optimizations for EJB invocations. That's why the remote-naming project for remote EJB invocations is considered "deprecated". ...
You can check how to do remote EJB invocations using the EJB client API here.
Found it....
The ones I used for Local machines only. Difference JBoss instances, should change the JNDI lookup name...
like
ejb:quote/quote.jar//QuoteFacadeEJB!com.xyz.life.service.ejb.QuoteFacade

Resources