I'm using Message Driven Beans. They are pooled, so there are many instances of them. I need to use JAXB unmarshaller in onMessage method. What I want is to create unmarshaller instances in init method, for example:
public class MyMDB implemetns MessageListener {
private Unmarshaller unmarshaller;
#PostConstruct
public void init() {
unmarshaller = JAXBContext.newInstance(...)
}
public void onMessage(Message message) {
// use unmarshaller
}
}
Should I bother about concurrency issues in this scenario? As far as I know unmarshaller isn't thread safe. Should I use ThreadLocal here?
Unmadshaller creation is light. You could hold the reference to the thread safe JAXBContext and then create a new Unmarshaller each time you need one.
Related
I'm trying to inject a DAO as a managed property.
public class UserInfoBean {
private User user;
#ManagedProperty("#{userDAO}")
private UserDAO dao;
public UserInfoBean() {
this.user = dao.getUserByEmail("test#gmail.com");
}
// Getters and setters.
}
The DAO object is injected after the bean is created, but it is null in the constructor and therefore causing NullPointerException. How can I initialize the managed bean using the injected managed property?
Injection can only take place after construction simply because before construction there's no eligible injection target. Imagine the following fictive example:
UserInfoBean userInfoBean;
UserDao userDao = new UserDao();
userInfoBean.setDao(userDao); // Injection takes place.
userInfoBean = new UserInfoBean(); // Constructor invoked.
This is technically simply not possible. In reality the following is what is happening:
UserInfoBean userInfoBean;
UserDao userDao = new UserDao();
userInfoBean = new UserInfoBean(); // Constructor invoked.
userInfoBean.setDao(userDao); // Injection takes place.
You should be using a method annotated with #PostConstruct to perform actions directly after construction and dependency injection (by e.g. Spring beans, #ManagedProperty, #EJB, #Inject, etc).
#PostConstruct
public void init() {
this.user = dao.getUserByEmail("test#gmail.com");
}
I'm running an enviroment with JSF + Primefaces + tomcat 6.0.32 in netbeans using EclipseLink (JPA 2.0).
My application works fine, but everytime I run it, I get a lot of warnings saying that cannot Serializate my session beans, and shows me blocks like this for every session bean:
18-jul-2012 23:05:46 org.apache.catalina.session.StandardSession writeObject
ADVERTENCIA: No puedo serializar atributo de sesión facturacionController para sesión 62A53325838E1E7C6EB6607B1E7965E6
java.io.NotSerializableException: org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
... and so on...
The thing is that my session beans already implements Serializable.
So what can I do to solve this ?
Thanks !
---- added info 07/20/2012 ----
The only point where I'm making a reference to EntityManager from the session bean is when I create the jpaController in the getter property, like this:
private JpaController getJpaController() {
if (jpaController == null) {
jpaController = new JpaController(Persistence.createEntityManagerFactory("myPersistenceUnit"));
}
return jpaControllerPedido;
}
That is because I defined the jpaController constructor like this:
public JpaController(EntityManagerFactory emf) {
this.emf = emf;
}
Making a class Serializable does not means everything in it will be serializable. All references(dependencies/properties) in your class, they themselves should be serializable and in turn their references.
As per above exception it seems your session bean is having reference to EntityManagerFactoryImpl object which is not serializable and hence the error.
To solve this you can define it as transient than it wont be serialized but only problem will be during de-serialization you will have to build the object or assign reference manually.
I suggest have a look at this article on Serilization.
How to solve this, I don't do JPA so cannot tell if there is some serialized class for same,
To solve it define the reference as transient
transient EntityManagerFactory entityManagerFactory
and assign the reference back to bean manually in deserialization hook method as described below.
private void readObject(java.io.ObjectInputStream stream)
throws java.io.IOException, ClassNotFoundException
{
stream.defaultReadObject();
// assign reference manually.
this.entityManagerFactory = //get from factory;
}
Hope this helps !!!!
You only add this:
transient EntityManagerFactory entityManagerFactory;
But if have any other Object that implement entityManagerFactory, this object must also be defined as. For Example
transient static final EntityManagerFactory emf = Persistence.createEntityManagerFactory("porpertiesConexion");
transient EntityManager em;
public void beginTransaction() {
em = emf.createEntityManager(); //
//code....
}
I'm trying to inject a DAO as a managed property.
public class UserInfoBean {
private User user;
#ManagedProperty("#{userDAO}")
private UserDAO dao;
public UserInfoBean() {
this.user = dao.getUserByEmail("test#gmail.com");
}
// Getters and setters.
}
The DAO object is injected after the bean is created, but it is null in the constructor and therefore causing NullPointerException. How can I initialize the managed bean using the injected managed property?
Injection can only take place after construction simply because before construction there's no eligible injection target. Imagine the following fictive example:
UserInfoBean userInfoBean;
UserDao userDao = new UserDao();
userInfoBean.setDao(userDao); // Injection takes place.
userInfoBean = new UserInfoBean(); // Constructor invoked.
This is technically simply not possible. In reality the following is what is happening:
UserInfoBean userInfoBean;
UserDao userDao = new UserDao();
userInfoBean = new UserInfoBean(); // Constructor invoked.
userInfoBean.setDao(userDao); // Injection takes place.
You should be using a method annotated with #PostConstruct to perform actions directly after construction and dependency injection (by e.g. Spring beans, #ManagedProperty, #EJB, #Inject, etc).
#PostConstruct
public void init() {
this.user = dao.getUserByEmail("test#gmail.com");
}
How to disable the validation on marshaller for jaxb1?
You could set a ValidationEventHandler on your marshaller that ignored all the events:
marshaller.setEventHandler(new IgnoringValidationEventHandler());
The ValidationEventHandler would look something like:
import javax.xml.bind.ValidationEvent;
import javax.xml.bind.ValidationEventHandler;
public class IgnoringValidationEventHandler implements ValidationEventHandler {
public boolean handleEvent(ValidationEvent event) {
return true;
}
}
Note:
If this is a new application I would recommend using JAXB 2 (JSR-222) instead of JAXB 1.
I want to customize the marshalling of dates in JAXB. It's a variant of this already asked question. I would think I would use an XMLAdapter, as this answer questions specifies.
But I can't do that exactly, because I'm going the other way around, generating the JAXB beans from an .XSD -- I can't add annotations to the JAXB beans because they are generated code.
I've tried calling Marshaller.setAdapter(), but with no luck.
final Marshaller marshaller = getJaxbContext().createMarshaller();
marshaller.setSchema(kniSchema);
marshaller.setAdapter(new DateAdapter());
...
private static class DateAdapter extends XmlAdapter<String, XMLGregorianCalendar> {
#Override
public String marshal(XMLGregorianCalendar v) throws Exception {
return "hello"; //Just a test to see if it's working
}
#Override
public XMLGregorianCalendar unmarshal(String v) throws Exception {
return null; // Don't care about this for now
}
}
Where the relevant part of my generated JAXB bean looks like this:
#XmlSchemaType(name = "date")
protected XMLGregorianCalendar activeSince;
When I do this, what the default date/XMLGregorianCalendar marshalling happens. It's as if I didn't do it all.
Any help is appreciated.
Thanks,
Charles