Delay start of JMS Listener (MDB) in JBoss 6.0 - jboss

we have multiple instances of JBoss-Server in a clustered environment. For background tasks there is a global queue available, that manages all jobs registered at it. For this queue there is a simple listener (MDB) on each node, manages the incoming messages. This listener does a manual lookup (no injection) for a singleton bean and starts a pre defined method.
Everything works fine so far, but the method in the singleton bean uses some other (no singleton services) that are not available under some circumstances.
For example if a node will be restarted and there are left messages in the queue (not processed yet) the messages will be picked up by the listener and all further beans are null, so the job produces a NPE.
Is it possible to define a delay time in JMS-Listener after messages will be picked up or is it possible to define an "application completely deployed" hook in there? The DependsOn-Annotation does not work, because of the usage of non singletons.
A possibility can be to set the MDB-property "DeliveryActive" to false and start the bean after full deployment. Is there a simple, working way to do this programatically (not in jmx-console)? Any manuals for this I found, redirects me to a manual jndi lookup. I think it have to be possible to inject the Bean per annotation and call startDelivery()? Is there a good place to do this in application?
Another hint takes me to the initialise in order property in application.xml, because the problem might be connected to JBoss Deployment order (some EJBs will be later available than the listener), but there seems to be a bug in JBoss 6.0 and upgrading to 6.1. is not an option. Maybe there is a walkthrough for this?
I hope that the problem is well enough explained, otherwise please ask for further informations.
Thanks in advance,
Danny
Additional informations:
JBoss 6.0.0 Final
HornetQ 2.2.5 Final (already updated, because of the buggy default version of JBoss)
The Listener:
#MessageDriven(activationConfig =
{
#ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
#ActivationConfigProperty(propertyName = "destination", propertyValue = "/queue/SchedulerQueue")
})
public class SchedulerQueueListener implements MessageListener {
...
#Override
public void onMessage(Message message) {
...
service = (IScheduledWorkerService) new InitialContext().lookup(jndiName);
EJobResult eJobResult = service.executeJob(message);
...
}
A sample worker:
#Singleton
#LocalBinding(jndiBinding = SampleJobWorkerService.JNDI_NAME)
public class SampleJobWorkerService implements IScheduledWorkerService {
...
#EJB(name = "SampleEJB/local")
private ISampleEJB sampleEjb;
...
#Override
public EJobResult executeJob(Message message) {
int state = sampleEjb.doSomething(message.getLongProperty(A_PROPERTY));
}
In this case the sampleEjb - member will be null sometimes

As a workaround, instead of calling EJB's directly from MDB, you can create a timer with a timeout with some delay. Therefore there will be some delay in execution.
In Timer's timeout method, then you can call singleton EJB, which in case will call other non-singleton EJB's.
JBoss specific : Can try setting the property in the message object before sending.
msg.setLongProperty("JMS_JBOSS_SCHEDULED_DELIVERY", (current + delay));
Other alternative is _JBM_SCHED_DELIVERY.
Edit :
For 1st part, you can have JTA transaction, which may span across JMS & EJB. Therefore failover & other things may be handled accordingly.
You can also increase the redelivery delay for the message object.
<address-setting match="jms.queue.someQueue">
<redelivery-delay>5000</redelivery-delay>
</address-setting>

I am in the same trouble at the moment.
I propose you use EJB 3 startup bean annotation #Startup on your singleton bean to invoke the startDelivery method on your Message listeners.

Related

Can I use SpringData by itself [duplicate]

I'm trying to wire up Spring Data JPA objects manually so that I can generate DAO proxies (aka Repositories) - without using a Spring bean container.
Inevitably, I will be asked why I want to do this: it is because our project is already using Google Guice (and on the UI using Gin with GWT), and we don't want to maintain another IoC container configuration, or pull in all the resulting dependencies. I know we might be able to use Guice's SpringIntegration, but this would be a last resort.
It seems that everything is available to wire the objects up manually, but since it's not well documented, I'm having a difficult time.
According to the Spring Data user's guide, using repository factories standalone is possible. Unfortunately, the example shows RepositoryFactorySupport which is an abstract class. After some searching I managed to find JpaRepositoryFactory
JpaRepositoryFactory actually works fairly well, except it does not automatically create transactions. Transactions must be managed manually, or nothing will get persisted to the database:
entityManager.getTransaction().begin();
repositoryInstance.save(someJpaObject);
entityManager.getTransaction().commit();
The problem turned out to be that #Transactional annotations are not used automatically, and need the help of a TransactionInterceptor
Thankfully, the JpaRepositoryFactory can take a callback to add more AOP advice to the generated Repository proxy before returning:
final JpaTransactionManager xactManager = new JpaTransactionManager(emf);
final JpaRepositoryFactory factory = new JpaRepositoryFactory(emf.createEntityManager());
factory.addRepositoryProxyPostProcessor(new RepositoryProxyPostProcessor() {
#Override
public void postProcess(ProxyFactory factory) {
factory.addAdvice(new TransactionInterceptor(xactManager, new AnnotationTransactionAttributeSource()));
}
});
This is where things are not working out so well. Stepping through the debugger in the code, the TransactionInterceptor is indeed creating a transaction - but on the wrong EntityManager. Spring manages the active EntityManager by looking at the currently executing thread. The TransactionInterceptor does this and sees there is no active EntityManager bound to the thread, and decides to create a new one.
However, this new EntityManager is not the same instance that was created and passed into the JpaRepositoryFactory constructor, which requires an EntityManager. The question is, how do I make the TransactionInterceptor and the JpaRepositoryFactory use the same EntityManager?
Update:
While writing this up, I found out how to solve the problem but it still may not be the ideal solution. I will post this solution as a separate answer. I would be happy to hear any suggestions on a better way to use Spring Data JPA standalone than how I've solve it.
The general principle behind the design of JpaRepositoryFactory and the according Spring integration JpaRepositoryFactory bean is the following:
We're assuming you run your application inside a managed JPA runtime environment, not caring about which one.
That's the reason we rely on injected EntityManager rather than an EntityManagerFactory. By definition the EntityManager is not thread safe. So if dealt with an EntityManagerFactory directly we would have to rewrite all the resource managing code a managed runtime environment (just like Spring or EJB) would provide you.
To integrate with the Spring transaction management we use Spring's SharedEntityManagerCreator that actually does the transaction resource binding magic you've implemented manually. So you probably want to use that one to create EntityManager instances from your EntityManagerFactory. If you want to activate the transactionality at the repository beans directly (so that a call to e.g. repo.save(…) creates a transaction if none is already active) have a look at the TransactionalRepositoryProxyPostProcessor implementation in Spring Data Commons. It actually activates transactions when Spring Data repositories are used directly (e.g. for repo.save(…)) and slightly customizes the transaction configuration lookup to prefer interfaces over implementation classes to allow repository interfaces to override transaction configuration defined in SimpleJpaRepository.
I solved this by manually binding the EntityManager and EntityManagerFactory to the executing thread, before creating repositories with the JpaRepositoryFactory. This is accomplished using the TransactionSynchronizationManager.bindResource method:
emf = Persistence.createEntityManagerFactory("com.foo.model", properties);
em = emf.createEntityManager();
// Create your transaction manager and RespositoryFactory
final JpaTransactionManager xactManager = new JpaTransactionManager(emf);
final JpaRepositoryFactory factory = new JpaRepositoryFactory(em);
// Make sure calls to the repository instance are intercepted for annotated transactions
factory.addRepositoryProxyPostProcessor(new RepositoryProxyPostProcessor() {
#Override
public void postProcess(ProxyFactory factory) {
factory.addAdvice(new TransactionInterceptor(xactManager, new MatchAlwaysTransactionAttributeSource()));
}
});
// Create your repository proxy instance
FooRepository repository = factory.getRepository(FooRepository.class);
// Bind the same EntityManger used to create the Repository to the thread
TransactionSynchronizationManager.bindResource(emf, new EntityManagerHolder(em));
try{
repository.save(someInstance); // Done in a transaction using 1 EntityManger
} finally {
// Make sure to unbind when done with the repository instance
TransactionSynchronizationManager.unbindResource(getEntityManagerFactory());
}
There must be be a better way though. It seems strange that the RepositoryFactory was designed to use EnitiyManager instead of an EntityManagerFactory. I would expect, that it would first look to see if an EntityManger is bound to the thread and then either create a new one and bind it, or use an existing one.
Basically, I would want to inject the repository proxies, and expect on every call they internally create a new EntityManager, so that calls are thread safe.

changing anotations from JBoss Seam to CDI (JEE6)

We are migrating our App from JBoss Seam to CDI (JEE6), so we are changing some anotations like #In and #Out, there's a lot of information that we have found helpful, but we have some troubles trying to find out how to replace anotations with particular patterns:
For #In anotation
#Name("comprobantes")//context name
...
#In(create=false,value="autenticadoPOJO",required=false)
private UsuarioPOJO autenticadoPOJO;
We can use #Inject from CDI, but how to set the name of the context variable for this case?.
For the #Out anotation
#Out(scope = ScopeType.SESSION, value = "autenticadoPOJO", required = false)
I have read some blogs and they say that I can use #Produces in CDI, how we can set the scope, before or after adding this anotation?
I appreciate any help or any helpful documentation.
I'm afraid there is no such thing like a 1:1 compatibility for #Out.
Technically, #Out in Seam 2 was realized by an interceptor for all method invocations - this turned out to be quite a performance bottleneck.
In CDI, most managed beans are proxied, this makes it technically impossible to implement outjection in the Seam 2 way.
What you can do (well, what you actually have to do) is going through all usages of #Out and replace it individually with some #Producer logic. Have a look at this official example here. In Seam 2, you would have outjected the authenticated user to the session-scope, in CDI a little producer method does (almost) the same.
That should hopefully give you a good start, feel free to ask further questions :)
http://docs.jboss.org/weld/reference/1.0.0/en-US/html/producermethods.html
8.1. Scope of a producer method
The scope of the producer method defaults to #Dependent, and so it will be called every time the container injects this field or any other field that resolves to the same producer method. Thus, there could be multiple instances of the PaymentStrategy object for each user session.
To change this behavior, we can add a #SessionScoped annotation to the method.
#Produces #Preferred #SessionScoped
public PaymentStrategy getPaymentStrategy() {
...
}

Explain RestEasy providers, resources and singletons in relation to classes vs instances?

I'm building a JAX-RS app that consists of a stockroom and a workplace. The stockroom holds a set of Java classes that can be instantiated (via AJAX) to create named instances of those classes in the workplace.
So far I'm able to reference the stockroom and workplace fine by declaring them as "singletons" in the RestEasy application
singletons.add(StockPlace.getInstance());
singletons.add(WorkPlace.getInstance());
I'm unable to understand how to understand how the stockroom content classes should be handled. The effect I'm trying to achieve is that when I dynamically create an instance of one of the stockroom classes, that instance can be dynamically accessed via REST commands. I've tried various permutations of:
classes.add(SomeComponent.class);
I think I'm missing knowledge of how the Java notion of how classes work as factories for making instances, and how both of these relate to what RestEasy calls classes, singletons (singletons ARE classes, yet RestEasy registers them as instances) and resources (instances?).
I suspect I'll wind up needing to dynamically register new instances but can't find a way to do that either. I did find a way to do it given the ServletContext, but am not able to get access to that either. Can someone get me on the right track?
Our eventual answer to this question was to bail out of RestEasy and convert to DropWizard. That problem and many others vanished and everything became easy again.
I believe I know what you are after, but I should at least give you a push in the right direction.
You will need to add the annotated RESTEasy class(es) to the registry. Below is the class I used for a recent project. It adds to the singletons (per what you did) but it also adds to the registry.
public class RESTEasyServerApplication extends javax.ws.rs.core.Application
{
// The RESTEasy registry
#Autowired
protected org.jboss.resteasy.spi.Registry registry;
// The annotated RESTEasy handler classes
private Set<Object> singletons = new HashSet<Object>();
private List<Object> handlers = new ArrayList<Object>();
public RESTEasyServerApplication()
{}
#Override
public Set<Object> getSingletons()
{
return singletons;
}
// Spring injection support
public void setHandlers( List<Object> handlers )
{
for( Object handler : handlers )
{
if( registry != null )
{
// Save a reference to the handler
this.handlers.add( handler );
// Register the handler with RESTEasy
registry.addSingletonResource( handler );
}
singletons.add( handler );
}
}
// Spring injection support
public List<Object> getHandlers()
{
return handlers;
}
}
I used Spring, and here is the relevant configuration:
<!-- RESTeasy/Spring integration -->
<import resource="classpath:springmvc-resteasy.xml" />
<!-- RESTeasy server application -->
<bean id="application" class="blah.blah.resteasy.RESTEasyServerApplication">
<property name="handlers">
<list>
<!-- Application specific handler classes -->
<ref bean="sample"/>
</list>
</property>
</bean>
Should be easy to modify/add a method to accept a single annotated RESTEasy class and make it work dynamically as required. The registry is defined in the springmvc-resteasy.xml file.
Since I've found no answers that don't involve strapping another whole layer of complexity (Spring) onto RestEasy, the solution I found livable is outlined in the final comment above. That is, don't rely on sending remote messages to instances unless the app is truly stateless (e.g. instances don't persist across messages). Only send remote messages to singletons which do persist across requests. Each such message can identify the desired instance (by String id in my case), and the singleton can forward to the identified instance as an ordinary POJO.
I still don't see why RestEasy unconditionally treats non-Singletons (instances) as ephemeral. Statelessness is not a restriction on REST, only a restriction on when GET methods can be used (idempotent calls). PUT and POST calls are neither stateless nor idempotent.
As I understand this, of course, and feel free to correct me. My focus is getting this app on the air, not exploring every corner of RestEasy, REST, and certainly not Spring.

Callback between EJBs / local EJB calls

Can you register EJB A as callback in an MDB B?
B.register(Aref)
in B: A.callback()
What would be Aref if the EJBs use local calls?
SessionContext.getEJBLocalObject()?
What you ask is not really possible in the proposed way.
If B is a Message Driven Bean, then it's never possible to call a method on it. In the messaging paradigm, the type of the receiver of a message is unknown. You thus can't reference an instance of the MDB. Instead, you post messages to a queue or topic and if your MDB is configured to listen to that its onMessage() method will be invoked.
Secondly, in EJB you don't often pass references around like in your example code. What kind of EJB bean is A supposed to be? A stateless session bean, or a stateful session bean?
In case it's a stateless session bean, the instance might not matter and you can probably just inject it:
#MessageDriven
public class NSMessageDrivenBean implements MessageListener {
#EJB
private A yourABean;
public void onMessage(Message message) {
// process message and then call A
yourABean.someMethod();
}
}
If the callback needs to be done to a type that is unknown in advance (depending on the message being send), then one mechanism for this is via a JMS reply.
In the message being send to the message driven bean, you then include code like this:
message.setJMSReplyTo(someDestination);
message.setJMSCorrelationID(someCorrelationID);
someDestination represents your callback, it's a destination to which something is listening, and this something can then invoke the call on the stateless session bean (in the context of the client).
E.g. something like:
connection.createSession(false, Session.AUTO_ACKNOWLEDGE).createConsumer(someDestination).setMessageListener(
new MessageListener() {
#Override
public void onMessage(Message message) {
yourABean.someMethod();
}
}
In this case, someDestination can be a temporary destination.

How does CDI injection work in MDBs and #Scheduled beans?

I'm working on a large Java EE 6 application that is deployed on JBoss 6 Final. My current tasks involve using #Inject consistently instead of #EJB, but I'm running into some problems on some types of beans, specifically #MessageDriven beans and beans with #Scheduled methods.
What happens is that if I'm unlucky with the timing (for #Schedule) or if there are messages in the MDBs' queues at startup, instantiation of the beans will fail because the injected resources (which are EJBs themselves) are not bound yet.
Because I use #Inject, I'm guessing that the EJB container considers my beans to be ready, since the container itself does not care about #Inject; it probably simply assumes that since there are no #EJB injections, the beans are ready for use. The injected CDI proxies will then fail because the resources to inject aren't actually bound yet.
Tiny example:
#Stateless
#LocalBean
public class MySupportingBean {
public void doSomething() {
...
}
}
#Singleton
public class MyScheduledBean {
#Inject
private MySupportingBean supportingBean;
#Schedule(second = "*/1", hour = "*", minute = "*", persistent = false)
public void onTimeout() {
supportingBean.doSomething();
}
}
The above example will probably not fail often because there are only two beans, but the project I'm working on binds lots of EJBs, which will amplify the problem. But it might fail because there is no guarantee that MySupportingBean is bound first, and if onTimeout is invoked before MySupportingBean is bound, then instantiation of MyScheduledBean will fail. If I used #EJB instead, MyScheduledBean wouldn't be bound until the dependency to MySupportingBean was satisfied.
Note that the example will not fail in onTimeout itself, but when CDI attempts to inject MySupportingBean.
I've read a lot of posts on different forums where many people argue that #Inject is always better. Generally, I agree, but how do they handle #Schedule or #MessageDriven combined with #Inject? In my experience, it comes down to dumb luck whether the beans will work or not in those cases, and the beans will fail arbitrarily, depending on which order the EJBs are deployed in, and when #Schedule or onMessage are invoked.
It might help to explicitly define the dependencies using the JBoss proprietary annotation #Depends or using the jboss.xml file.
See this for a somewhat similar question: How to order deployment of EJBs and JMS queue config in JBoss 5?