Is it possible to invoke a MessageDrivenBean remotely directly through a #Remote interface? - jms

I am currently learning the basics of EJB 2+. In the book Java EE 7 The Big Picture, it was mentioned:
Session beans are generally accessed through a remote interface (though, as we shall see, there are cases where a remote interface is not required), while message-driven beans have only a bean implementation class.
Based on the statement above, invoking a message-driven bean (MDB) just like invoking a remote session bean through a remote interface, whose server-side interface is done with #Remote annotation, seems to be impossible.
For instance, if there is a MDB on a remote EJB container:
#Remote
#MessageDriven(mappedName="jms/HelloQueue")
public class HelloMDB implements MessageListener {
public void onMessage(Message msg) {
//implementation
}
}
Question: can the MDB mentioned above be invoked at all by a remote client directly and programmatically .e.g. through JNDI?

No, an MDB cannot be invoked by a remote client directly as noted in this Java EE 7 tutorial from Oracle which states:
Client components do not locate message-driven beans and invoke methods directly on them.
If you want to invoke the MDB's onMessage then simply send a message to the destination where it's listening.

Related

Spring Batch Bean Scope to convert Legacy Application

We have a legacy normal java application with below architectural flow
Facade ----> Corba remote IIOP Connection --> ServiceCommands
Above architecture we wants to convert as SpringBeans(Spring Boot) and call from MVCController and expose as RESTAPI
MVCController ---> Facade -->Corba Connection -->ServiceCommands
Please advise what is the Bean scope to be used for each layer and best architecture to be followed
Facade class Bean - Scope value="session"
CorbaConnection Class bean Scope value="session"
ServiceClass bean Scope value="singleton"
We have solved the issue by created a Corba connection Pool and make each connection from the pool is a Spring bean with scope "Session". Every session request to corba will be in Proxy mode and commit when the #service finishes. All the properties of pools has been added to maintain idle time and re-connection and return back to the pool after the service finishes. Service and Facade remains singleton bean. Thanks team for the support again to provide idea hints from your experiences.

Spring AMQP ListenerContainer lifecycle management

We are using Spring AMQP to connect to RabbitMQ in our Spring based web application.
When we declare our listener-containers as beans (using rabbit:listener-container) in application context, their lifecycle is managed by Spring.
If we declare a listener-container in a component inside a #PostConstruct method, or we create a bean with class org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer as a prototype scoped bean, we then have to manage the lifecycle i.e. start and stop the listener-container ourselves.
My question is, if we declare new queues, bindings and listener-containers inside a #PostConstruct method, just calling listener.stop/shutdown/destroy method inside the corresponding #PreDestroy method would be enough for a graceful shutdown? Or else what do I need to do?
Note: I am guessing I don't have to do anything for the new queues and bindings created in the #PostContruct, but I would be very glad if you also confirm this for me.
I would not recommend starting a listener container or declaring queues/bindings in an #PostConstruct method; the context is only half-baked at that time. It might work but it's not recommended to do stuff like that while the context is being initialized.
It's better to implement SmartLifecycle and start/stop them in the start()/stop() methods.
Then, the container lifecycles would be indirectly managed by the spring context.
You can also control exactly when your bean is started/stopped by putting it in a phase.

What are the techniques to manage "session" or invocation context for Stateless EJBs during Remote calls?

I am writing an application that uses RMI to invoke EJBs. The EJBs are Stateless; the business requirements do not require conversational state with the client.
One of the parameters to the EJB method calls is a "User" object used to determine if the user associated with the call has permission to perform the action. We are not using container-managed auth-auth: the User object is just a POJO provided by the remote client.
I would like to make this User object globally available/injectable within the "session" or invocation context. I am aware that Stateless EJBs do not have a "session" in the EJB sense; what I mean by "session" is "the current invocation". For example, say we have only one remote EJB with two methods:
myStatelessEjb.add(Thing, User)
myStatelessEjb.update(Thing, User)
These methods call many more methods: there are other EJBs involved, Bean Validators, etc. Rather than passing-around the User object everywhere, I would like to make the User object globally available/injectable with the context of the current remote EJB invocation.
I could of course just pass around the User object or encapsulate it with "Thing", but I thought maybe it would be a better design to not "pollute" my objects and APIs with User since it's a cross-cutting concern.
Notes (for emphasis):
I am using RMI.
There is no HTTP session, because I am using RMI.
I am not using container-managed auth-auth.
I am using container-managed transactions.
Is there a standard technique suitable for this problem? e.g. Perhaps the remote client should invoke a Stateful EJB which will hold the User, or maybe ThreadLocal is appropriate, or maybe I can hook onto the container-managed transaction, or maybe there's already an applicable session/context I'm unaware of.
Easiest way would be to store the user in a #RequestScoped CDI bean and inject that as required:
#RequestScoped
public class RequestUser {
private User user;
//getter and setter for user
}
#Remote
#Statless
public class MyRemoteInterface {
#Inject
private RequestUser requestUser;
...
public void foo(User user, Bar bar) {
request.setUser(user);
...
}
}
#Stateless
public class OtherEJB() {
#Inject
private RequestUser user;
public void doBar(Bar bar) {
User user = user.getUser();
...
}
}
While #SessionScoped is useful for HTTP sessions only, #RequestScoped has broader applicability:
public #interface RequestScoped
Specifies that a bean is request scoped.
The request scope is active:
during the service() method of any servlet in the web application, during the doFilter() method of any servlet filter and when the
container calls any ServletRequestListener or AsyncListener,
during any Java EE web service invocation,
during any remote method invocation of any EJB, during any asynchronous method invocation of any EJB, during any call to an EJB
timeout method and during message delivery to any EJB message-driven
bean, and
during any message delivery to a MessageListener for a JMS topic or queue obtained from the Java EE component environment.

Spring Bean Container

I wanted to write test cased for testing my service using springjunit runner.
My service will call another service and transform its out put and send the response.
I thouhgt that server need to be up and running for calling the other service while running junit.
But I was told that spring junit doesnt need server to be running.
Spring container will do the magic it seems.
Am not pretty sure how this happens.
Can any one enlighten me with how spring container can act as server?
If its so silly quesiton,sorry for that.Thanks in advance
do you need server to run java.class , answer is no, untill unless if you have any ejb component to be called from your service, or you service need some external web service to
respond (here you may need to either mock this service to give mock data or run the service on server)
i have service which calls data access layer , sometimes service calls another service.
all you need to have spring context configuration in your test class
#ContextConfiguration({ "classpath:spring-context.xml", "classpath:otherservice-context.xml"})
#RunWith(SpringJUnit4ClassRunner.class)
#Component
public class TestJuint{
#Autowire
private otherService otherServiceImpl;
#Autowire
private service serviceImpl;
#Test
public void testDummy{
serviceImpl.addDummy(dummyObj);
}
}
suppose if you need to have another service from some other package then you might want to include its context file in context configuration, so that its bean reference will be in spring context while autowiring

Java EE 6: controlling startup of managed beans with dependencies: CDI, EJB

I just read the very nice explanation of the various managed beans and their relations on Java EE 6 #javax.annotation.ManagedBean vs. #javax.inject.Named vs. #javax.faces.ManagedBean and as i face a annoying problem in my application i want to know if it is possible to control or influence the way how and when beans are started.
In my Java EE application I use EJB, CDI and JSF2 as view technology. Via SPI a service from a third party is booted and it configures a job executor which starts jobs and handles other timer relevant stuff. One job is immediately executed when the job executor finished its bootstrapping. This job uses CDI inject to get access to some beans and one of these beans make use of an EJB.
The problem is now that most of the time the Java EE 6 server (JBoss 7.1.1) starts the EJB is still not available then the job tries to access it. An exceptions is thrown and the job fails and the service is build to deactivate that failed job. Well, deactivating a faild job seems to be not too bad. The only solution for the job to get up and running again is to undeploy it and to redeploy it again. Which is a manual task unfortunately and it can not be done programmatically.
And, to make things bad: in rare cases this does not happen.
So, my question now is: can i somehow control the initialisation and deployment of the EJB and CDI beans so that i can ensure that all EJB beans are initialzed before the CDI beans are initialized?
I have set initialize-in-order to true in the EARs application.xml and set the sequence of the EJBs so that they get initialized they way i need them (EJB core, then EJB business, then WAR), but the CDI based service is placed as JAR in the lib folder.
Excerpt from Java EE 6 Tutorial with some modifications:
#Singleton
#Startup
public class BeanA { ... }
#Qualifier
#Target({FIELD, PARAMETER})
#Retention(RUNTIME)
public #interface EjbStarted {}
#Singleton
#Startup
#DependsOn("BeanA", "BeanB", "BeanC")
public class LastBean {
#Inject #EjbStarted Event<String> event;
#PostConstruct
public void startService() {
// At this moment PrimaryBean is ready for use
event.fire("LastBean");
}
}
public class CDIService {
public void start(#Observes #EjbStarted String name) {
if("LastBean".equals(name)) {
startService();
}
}
}
UPDATE: While thinking about the problem, I somehow forgot that you want the initialization order in CDI beans, so the answer is somewhat out of context, sorry about that :)
UPDATE 2: Added how to make a CDI service start after EJBs

Resources