How to get a static List from a Message Driven Bean? - queue

I am using a Message Driven Bean for storing messages in a list as you can see in the code given below:
/**
*
* #author sana-naeem
*/
#MessageDriven(mappedName = "jms/Queue-0", activationConfig = {
#ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
#ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
})
public class MyMessageBean implements MessageListener{
private static ArrayList<String> list = new ArrayList<String>();
public MyMessageBean() {
}
#Override
public void onMessage(Message message) {
Textmessage msg = (TextMessage) message;
try {
if (message instanceof TextMessage) {
list.add("Messages: "+msg.getText());
} else {
System.out.println("No Text!!!");
}
} catch (JMSException ex) {
System.out.println("JMS.Exception....!!!");
}
}
public static ArrayList<String> getList() {
return list;
}
public void setList(ArrayList<String> list) {
this.list = new ArrayList<String>();
}
}
Now the problem is when I access the getter method from another Java Class; it is displaying list size=0;
Can I please know why is this happening;
I want to get that list in another Java Class;
If there is something wrong with the Queue, kindly let me know How to fix it???
It was working fine before;
Actually, previously I was using a Servlet to send messages but now, I am using a simple Java class with some initial context parameters defined...; so now the list is not working as expected...
Any advice or suggestion would be highly appreciable.
Thank you!

You shouldn't be using mutable static fields in an MDB. When you think MDB, think stateless, because that's how the container treats them. Here is a good reference;
http://www.coderanch.com/t/312086/EJB-JEE/java/Clarification-static-fields
Unfortunately, there isn't one single answer for your question. Without knowing anything about the rest of your application, how it is designed, what components you are using, how they interact, how it will be deployed, etc., it is difficult to give advice. But the first thing that comes to mind, given what limited information I have, is that you can create a separate object to wrap a Private ArrayList, and store a reference to that object in an appropriate context. Your MDB can then access that object. In that case, you'd have methods in the object to modify/read the ArrayList, and you'd synchronize these methods internally on the underlying ArrayList because the methods will be accessible by multiple threads.
But this is a brute force approach, not knowing anything else about your application. And depending on how your application is designed and deployed, this might not be the right advice. But the point here is that;
You need to separate your stateful object from what is intended to be a stateless object.
You need to make it accessible from an appropriate context.
You need to synchronize modify/read methods on the underlying POJO (ArrayList) if the containing object will be accessible by multiple threads.

Related

FlatFileItemWriter write header only in case when data is present

have a task to write header to file only if some data exist, other words if reader return nothing file created by writer should be empty.
Unfortunately FlatFileItemWriter implementation, in version 3.0.7, has only private access fields and methods and nested class that store all info about writing process, so I cannot just take and overwrite write() method. I need to copy-paste almost all content of FlatFileItemWriter to add small piece of new functionality.
Any idea how to achieve this more elegantly in Spring Batch?
So, finally found a less-more elegant solution.
The solution is to use LineAggregators, and seems in the current implementation of FlatFileItemWriter this is only one approach that you can use safer when inheriting this class.
I use separate line aggregator only for a header, but the solution can be extended to use multiple aggregators.
Also in my case header is just predefined string, thus I use PassThroughLineAggregator by default that just return my string to FlatFileItemWriter.
public class FlatFileItemWriterWithHeaderOnData extends FlatFileItemWriter {
private LineAggregator lineAggregator;
private LineAggregator headerLineAggregator = new PassThroughLineAggregator();
private boolean applyHeaderAggregator = true;
#Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(headerLineAggregator, "A HeaderLineAggregator must be provided.");
super.afterPropertiesSet();
}
#Override
public void setLineAggregator(LineAggregator lineAggregator) {
this.lineAggregator = lineAggregator;
super.setLineAggregator(lineAggregator);
}
public void setHeaderLineAggregator(LineAggregator headerLineAggregator) {
this.headerLineAggregator = headerLineAggregator;
}
#Override
public void write(List items) throws Exception {
if(applyHeaderAggregator){
LineAggregator initialLineAggregator = lineAggregator;
super.setLineAggregator(headerLineAggregator);
super.write(getHeaderItems());
super.setLineAggregator(initialLineAggregator);
applyHeaderAggregator = false;
}
super.write(items);
}
private List<String> getHeaderItems() throws ItemStreamException {
// your actual implementation goes here
return Arrays.asList("Id,Name,Details");
}
}
PS. This solution assumed that if method write() called then some data exist.
Try this in your writer
writer.setShouldDeleteIfEmpty(true);
If you have no data, there is no file.
In other case, you write your header and your items
I'm thinking of a way as below.
BeforeStep() (or a Tasklet) if there is no Data at all, you set a flag such as "noData" is 'true'. Otherwise will be 'false'
And you have 2 writers, one with Header and another one without Header. In this case you can have a base Writer acts as a parent and then 2 writers inherits it. The only difference between them is one with Header and one doesn't have HeaderCallBack.
Base on the flag, you can switch to either 'Writer with Header' or 'Writer without Header'
Thanks,
Nghia

Generic way to initialize a JPA 2 lazy association

So, the question at hand is about initializing the lazy collections of an "unknown" entity, as long as these are known at least by name. This is part of a more wide effort of mine to build a generic DataTable -> RecordDetails miniframework in JSF + Primefaces.
So, the associations are usually lazy, and the only moment i need them loaded is when someone accesses one record of the many in the datatable in order to view/edit it. The issues here is that the controllers are generic, and for this I also use just one service class backing the whole LazyLoading for the datatable and loading/saving the record from the details section.
What I have with come so far is the following piece of code:
public <T> T loadWithDetails(T record, String... associationsToInitialize) {
final PersistenceUnitUtil pu = em.getEntityManagerFactory().getPersistenceUnitUtil();
record = (T) em.find(record.getClass(), pu.getIdentifier(record));
for (String association : associationsToInitialize) {
try {
if (!pu.isLoaded(record, association)) {
loadAssociation(record, association);
}
} catch (..... non significant) {
e.printStackTrace(); // Nothing else to do
}
}
return record;
}
private <T> void loadAssociation(T record, String associationName) throws IntrospectionException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
BeanInfo info = Introspector.getBeanInfo(record.getClass(), Object.class);
PropertyDescriptor[] props = info.getPropertyDescriptors();
for (PropertyDescriptor pd : props) {
if (pd.getName().equals(associationName)) {
Method getter = pd.getReadMethod();
((Collection) getter.invoke(record)).size();
}
}
throw new NoSuchFieldException(associationName);
}
And the question is, did anyone start any similar endeavor, or does anyone know of a more pleasant way to initialize collections in a JPA way (not Hibernate / Eclipselink specific) without involving reflection?
Another alternative I could think of is forcing all entities to implement some interface with
Object getId();
void loadAssociations();
but I don't like the idea of forcing my pojos to implement some interface just for this.
With the reflection solution you would suffer the N+1 effect detailed here: Solve Hibernate Lazy-Init issue with hibernate.enable_lazy_load_no_trans
You could use the OpenSessionInView instead, you will be affected by the N+1 but you will not need to use reflection. If you use this pattern your transaction will remain opened until the end of the transaction and all the LAZY relationships will be loaded without a problem.
For this pattern you will need to do a WebFilter that will open and close the transaction.

wicket :how to combine CompoundPropertyModel and LoadableDetachableModel

I want to achieve two goals:
I want my model to be loaded every time from the DB when it's in a life-cycle (for every request there will be just one request to the DB)
I want my model to be attached dynamically to the page and that wicket will do all this oreable binding for me
In order to achieve these two goals I came to a conclusion that I need to use both CompoundPropertyModel and LoadableDetachableModel.
Does anyone know if this is a good approach?
Should I do new CompoundPropertyModel(myLoadableDetachableModel)?
Yes, you are right, it is possible to use
new CompoundPropertyModel<T>(new LoadableDetachableModel<T> { ... })
or use static creation (it does the same):
CompoundPropertyModel.of(new LoadableDetachableModel<T> { ... })
that has both features of compound model and lazy detachable model. Also detaching works correctly, when it CompoudPropertyModel is detached it also proxies detaching to inner model that is used as the model object in this case.
I use it in many cases and it works fine.
EXPLANATION:
See how looks CompoundPropertyModel class (I'm speaking about Wicket 1.6 right now):
public class CompoundPropertyModel<T> extends ChainingModel<T>
This mean, CompoundPropertyModel adds the property expression behavior to the ChainingModel.
ChainingModel has the following field 'target' and the constructor to set it.
private Object target;
public ChainingModel(final Object modelObject)
{
...
target = modelObject;
}
This take the 'target' reference to tho object or model.
When you call getObject() it checks the target and proxies the functionality if the target is a subclass of IModel:
public T getObject()
{
if (target instanceof IModel)
{
return ((IModel<T>)target).getObject();
}
return (T)target;
}
The similar functionality is implemented for setObject(T), that also sets the target or proxies it if the target is a subclass of IModel
public void setObject(T object)
{
if (target instanceof IModel)
{
((IModel<T>)target).setObject(object);
}
else
{
target = object;
}
}
The same way is used to detach object, however it check if the target (model object) is detachable, in other words if the target is a subclass if IDetachable, that any of IModel really is.
public void detach()
{
// Detach nested object if it's a detachable
if (target instanceof IDetachable)
{
((IDetachable)target).detach();
}
}

Can't insert new entry into deserialized AutoBean Map

When i try to insert a new entry to a deserialized Map instance i get no exception but the Map is not modified. This EntryPoint code probes it. I'm doing anything wrong?
public class Test2 implements EntryPoint {
public interface SomeProxy {
Map<String, List<Integer>> getStringKeyMap();
void setStringKeyMap(Map<String, List<Integer>> value);
}
public interface BeanFactory extends AutoBeanFactory {
BeanFactory INSTANCE = GWT.create(BeanFactory.class);
AutoBean<SomeProxy> someProxy();
}
#Override
public void onModuleLoad() {
SomeProxy proxy = BeanFactory.INSTANCE.someProxy().as();
proxy.setStringKeyMap(new HashMap<String, List<Integer>>());
proxy.getStringKeyMap().put("k1", new ArrayList<Integer>());
proxy.getStringKeyMap().put("k2", new ArrayList<Integer>());
String payload = AutoBeanCodex.encode(AutoBeanUtils.getAutoBean(proxy)).toString();
proxy = AutoBeanCodex.decode(BeanFactory.INSTANCE, SomeProxy.class, payload).as();
// insert a new entry into a deserialized map
proxy.getStringKeyMap().put("k3", new ArrayList<Integer>());
System.out.println(proxy.getStringKeyMap().keySet()); // the keySet is [k1, k2] :-( ¿where is k3?
}
}
Shouldn't AutoBeanCodex.encode(AutoBeanUtils.getAutoBean(proxy)).toString(); be getPayLoad()
I'll check the code later, and I don't know if that is causing the issue. But it did stand out as different from my typical approach.
Collection classes such as java.util.Set and java.util.List are tricky because they operate in terms of Object instances. To make collections serializable, you should specify the particular type of objects they are expected to contain through normal type parameters (for example, Map<Foo,Bar> rather than just Map). If you use raw collections or maps you will get bloated code and be vulnerable to denial of service attacks.
Font: http://www.gwtproject.org/doc/latest/DevGuideServerCommunication.html#DevGuideSerializableTypes

How to make JPA EntityListeners validate the existence of an interface

I am working in J2EE 5 using JPA, I have a working solution but I'm looking to clean up the structure.
I am using EntityListeners on some of the JPA objects I am persisting, the listeners are fairly generic but depend on the beans implementing an interface, this works great if you remember to add the interface.
I have not been able to determine a way to tie the EntityListener and the Interface together so that I would get an exception that lead in the right direction, or even better a compile time error.
#Entity
#EntityListener({CreateByListener.class})
public class Note implements CreatorInterface{
private String message;....
private String creator;
....
}
public interface CreatorInterface{
public void setCreator(String creator);
}
public class CreateByListener {
#PrePersist
public void dataPersist(CreatorInterface data){
SUser user = LoginModule.getUser();
data.setCreator(user.getName());
}
}
This functions exactly the way I want it to, except when a new class is created and it uses the CreateByListener but does not implement the CreatorInterface.
When this happens a class cast exception is thrown somewhere deep from within the JPA engine and only if I happen to remember this symptom can I figure out what went wrong.
I have not been able to figure a way to require the interface or test for the presence of the interface before the listener would be fired.
Any ideas would be appreciated.
#PrePersist
public void dataPersist(Object data){
if (!(data instanceof CreatorInterface)) {
throw new IllegalArgumentException("The class "
+ data.getClass()
+ " should implement CreatorInterface");
}
CreatorInterface creatorInterface = (CreatorInterface) data;
SUser user = LoginModule.getUser();
creatorInterface.setCreator(user.getName());
}
This does basically the same thing as what you're doing, but at least you'll have a more readable error message indicating what's wrong, instead of the ClassCastException.