We need to audit the existing table using envers. we don't have hibernate.xml instead of we are using application-context.xml. And we are creating schema through "liquibase-changeset", then how do I create through annotations like #Entity and #Audited.
How do I solve this issue?
I have added hibernate configuration likes
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
<prop key="hibernate.ejb.event.post-insert">org.hibernate.ejb.event.EJB3PostInsertEventListener,org.hibernate.envers.event.AuditEventListener</prop>
<prop key="hibernate.ejb.event.post-update">org.hibernate.ejb.event.EJB3PostUpdateEventListener,org.hibernate.envers.event.AuditEventListener</prop>
<prop key="hibernate.ejb.event.post-delete">org.hibernate.ejb.event.EJB3PostDeleteEventListener,org.hibernate.envers.event.AuditEventListener</prop>
<prop key="hibernate.ejb.event.pre-collection-update">org.hibernate.envers.event.AuditEventListener</prop>
<!-- <prop key="hibernate.ejb.event.pre-collection-remove">org.hibernate.envers.event.AuditEventListener</prop>
<prop key="hibernate.ejb.event.post-collection-recreate">org.hibernate.envers.event.AuditEventListener</prop> -->
<prop key="org.hibernate.envers.revision_field_name">REV</prop>
<prop key="org.hibernate.envers.revision_type_field_name">REVTYPE</prop>
<prop key="org.hibernate.envers.auditTablePrefix"></prop>
<prop key="org.hibernate.envers.auditTableSuffix">_HISTORY</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
Added #Audited annotation in my domain class
#Entity
#Audited
#Table(name="user")
public class User implements Serializable {
But this configuration deleted my existing tables
e.g
Mydatabase
-----------
user
product
order_details
user_role
login
I have 5 tables in my database. After running my application it displays 3 tables. Instead of creating "audit" table, it deletes the existing table.
Mydatabase
-----------
user
product
order_details
How to create audit(_HISTORY) table without touching existing tables???
In the Liquibase changeset define the audit table definition like you would for any other table.
Skip the hibernate.hbm2ddl.auto property in spring-hibernate ocnfiguration.That will instruct hibernate to not do anything to the schema.
Keeping rest of your configuartion as it is, this should work.
Just ensure the audit tables names in schema and in configuration match.
Link to doc detailing how its done in case schema is generated using ant
I was facing the same issue, to resolve it, I followed the next steps:
change :
<prop key="hibernate.hbm2ddl.auto">create</prop>
to:
<prop key="hibernate.hbm2ddl.auto">update</prop>
If you work with ENVERS Hibernet-envers 3.5.5 or + you should have this configuration in your application-context:
<property name="eventListeners">
<map>
<entry key="post-insert" >
<bean class="org.hibernate.envers.event.AuditEventListener" />
</entry>
<entry key="post-update">
<bean class="org.hibernate.envers.event.AuditEventListener" />
</entry>
<entry key="post-delete">
<bean class="org.hibernate.envers.event.AuditEventListener" />
</entry>
<entry key="pre-collection-update">
<bean class="org.hibernate.envers.event.AuditEventListener" />
</entry>
<entry key="pre-collection-remove">
<bean class="org.hibernate.envers.event.AuditEventListener" />
</entry>
<entry key="post-collection-recreate">
<bean class="org.hibernate.envers.event.AuditEventListener" />
</entry>
</map>
</property>
You have to define a revision entity like this one:
#Entity
#Table(name = "MY_REVINFO")
#RevisionEntity(MyRevisionListener.class)//#see next class
public class MyRevisionEntity {
private static final long serialVersionUID =1L;
#Id
#GeneratedValue
#RevisionNumber
private int id;
#RevisionTimestamp
private long timestamp;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Transient
public Date getRevisionDate() {
return new Date(timestamp);
}
#Column(name = "USER_NAME")
private String userName;
#Column(name = "DATE_OPER")
private Date dateOperation;
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof DefaultRevisionEntity)) return false;
DefaultRevisionEntity that = (DefaultRevisionEntity) o;
if (id != that.getId()) return false;
if (timestamp != that.getTimestamp()) return false;
return true;
}
public int hashCode() {
int result;
result = id;
result = 31 * result + (int) (timestamp ^ (timestamp >>> 32));
return result;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Date getDateOperation() {
return dateOperation;
}
public void setDateOperation(Date dateOperation) {
this.dateOperation = dateOperation;
}
public String toString() {
return "DefaultRevisionEntity(id = " + id + ", revisionDate = " + DateFormat.getDateTimeInstance().format(getRevisionDate()) + ")";
}
}
Add the mapping of this new entity in your application-context.xml as :
<value>mypackage.MyRevisionEntity</value>
Create the listener (it's very helpfull if you want to save the user name and the operation time):
public class MyRevisionListener implements RevisionListener {
public void newRevision(Object revisionEntity) {
MyRevisionEntity revision = (MyRevisionEntity) revisionEntity;
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
String userName="---";
if (userDetails != null) {
userName=userDetails.getUsername();
} else {
userName="UNKNOWN";
}
revision.setUserName(userName);
revision.setDateOperation(new Date(revision.getTimestamp()));
}
}
Clean, install and run your application.
If the problem persists try to upgrade your Envers version (Hibrenate-envers and Hibernate-core)
Hope this help.
Try changing the DDL strategy from:
<prop key="hibernate.hbm2ddl.auto">create</prop>
to:
<prop key="hibernate.hbm2ddl.auto">update</prop>
The update DDL generation strategy shouldn't delete any existing table.
I'm working on a project using JPA with Hibernate implementation and we managed to make envers work without many problems using Spring context xml based configuration only (we neither use persistence.xml).
Our configuration is bassed on Spring JPA support but it's possible that you can find a similar solution:
<bean id="projectEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
</bean>
</property>
<property name="packagesToScan">
<list>
<value>com.teimas.myproject.bo</value>
<value>com.teimas.myproject.bo.commons</value>
<value>com.teimas.myproject.bo.util</value>
</list>
</property>
<property name="persistenceUnitName" value="projectPU" />
<property name="jtaDataSource" ref="projectDataSourceTarget" />
<!-- Other ptops for hibernate config -->
<property name="jpaProperties" ref="jpaHibernateProperties" />
</bean>
<util:properties id="jpaHibernateProperties">
<prop key="hibernate.transaction.jta.platform">
org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform
</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<!-- validate | update | create | create-drop -->
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="javax.persistence.transactionType">JTA</prop>
<prop key="javax.persistence.validation.mode">AUTO</prop>
</util:properties>
The key is that we use as JPA provider a hibernate object: org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter and we add packagesToScan property to tell hibernate to scan for annotations in those packages. So Hibernate find Envers and Validation anotations, and all work fine.
Hope this helps.
Related
In DAO:
private Map<Integer,String> departments = new LinkedHashMap<Integer, String>();
#Override
public List<DepartmentEntity> getAllDepartments() {
return this.sessionFactory.getCurrentSession().createQuery("from DepartmentEntity de order by LOWER(de.departmentname)").list();
}
#Override
public Map<Integer, String> loadDepartments() {
departments.clear();
for (DepartmentEntity de : getAllDepartments())
departments.put(de.getDepartmentid(), de.getDepartmentname());
return departments;
}
Its Working fine, but in spring creation of objects manually its bad code
private Map<Integer,String> departments;
So, how to inject map object of LinkedHashMap type from out side in my case ?.
I tried but i got exceptions like null pointer exception
Please any one help me..
<util:map id="myMap" map-class="java.util.LinkedHashMap" key-type="java.lang.Integer" value-type="java.lang.String"/>
<bean id="departmentDAOImpl" class="com.leadwinner.infra.assets.dao.DepartmentDAOImpl">
<property name="departments" ref="myMap"></property>
</bean>
You can do something like below:
eg.
class A{
private B b;
public setB(B b){
this.b = b;
}
public Map getMapFromA(){
return b.getMap();
}
}
class B{
private Map tmp;
public void setMap(HashMap t){
tmp.putAll(t);
}
public HashMap getMap(){
return tmp;
}
}
And in web.xml
<bean id="classB" class="default.B"/>
<bean id ="classA" class="default.A"/>
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject"><ref local="classA"></property>
<property name="targetMethod"><value>setB</value></property>
<property name="arguments"><ref local="classB"/></property>
</bean>
Now spring beans are by default singleton scoped. So you can do the following.
function do(){
B b = ctx.getBean("classB");
b.setMap(someMap);
A a = ctx.getBean("classA");
a.getMapFromA();
}
I havent tried out the code but it will give you an idea I hope so. More details on MethodInvokingFactoryBean : here
And if you dont want to do it by Spring and if you want less efforts try using ThreadLocal to pass parameters.
Populate map in this way (using constructor injection):
<bean name="DAO" class="path.to.yourDAOClass">
<constructor-arg index="0">
<map>
<entry key="1" value="One" />
<entry key="2" value="Two" />
</map>
</constructor-arg>
<bean>
By default target class for <map /> is a LinkedHashMap, but you can change target class using a MapFactoryBean to construct your map object in this way by replace the <map /> tag with:
<bean class="org.springframework.beans.factory.config.MapFactoryBean">
<property name="targetMapClass">
<value>java.util.HashMap</value>
</property>
<property name="sourceMap">
<map>
<entry key="1" value="One" />
<entry key="2" value="Two" />
</map>
</property>
</bean>
I am using spring / hibernate / mysql and currently using the following settings in spring-hibernate.xml
I am constantly seeing "select ##session.tx_read_only" and "select ##session.tx_isolation" queries being sent to the DB mostly after select statements for actual data.
Each of these queries add like 20-25ms time and I get like 70 queries run against the DB on a Oauth login. How can I get rid of them ?
I tried statelessSessions and the queries disappeared and I could reduce the number of queries to the application queries only but I read that using statelessSessions will not provide any first-level cache and its also vulnerable to data aliasing effects.
How can I avoid the "select ##session.tx_read_only" and select ##session.tx_isolation" running multiple times.(I use a generic Dao to access the DB a extract is given below) i am using findById, findAll, getNamedQueryAndNamedParam methods...
spring-hibernate.xml
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="${JDBC_CON_STRING}" />
<property name="user" value="${USER_NAME}" />
<property name="password" value="${USER_PASSWORD}" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.model" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">false</prop>
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.provider_configuration_file_resource_path">ehcach.xml</prop>
<prop key="hibernate.auto_close_session">true</prop>
</property>
<property name="mappingResources">
<list>
<value>named-queries.xml</value>
<value>native-named-queries.xml</value>
</list>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="testClassDao" class="com.dao.GenericHibernateDao">
<property name="clazz" value="com.model.TestClass" />
</bean>
GenericHibernateDao.java
#Repository
#Scope("prototype")
public class GenericHibernateDao<T, PK extends Serializable> implements GenericDao<T, PK> {
private Class<T> clazz;
#Autowired
private SessionFactory sessionFactory;
public void setClazz(final Class<T> clazzToSet) {
this.clazz = clazzToSet;
}
protected Session getSession() {
return sessionFactory.getCurrentSession();
}
protected Session getOpenSession() {
return sessionFactory.openSession();
}
#Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
public T findById(PK id) {
Object obj = null;
obj = getSession().get(clazz, id);
//obj = getStatelessSession().get(clazz, id);
return (T) obj;
}
#Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
public List<T> findAll() {
String queryString = "from " + clazz.getName();
Query query = getSession().createQuery(queryString);
query.setCacheable(true);
List<T> list = query.list();
return list;
}
#Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
public List<T> getNamedQuery(String queryName) {
Query query = getSession().getNamedQuery(queryName);
//Query query = getStatelessSession().getNamedQuery(queryName);
query.setCacheable(true);
List<T> results = query.list();
return results;
}
#Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
public List<T> getNamedQueryAndNamedParam(String queryName, String paramName, Object value) {
Query query = getSession().getNamedQuery(queryName).setString(paramName, value.toString());
query.setCacheable(true);
List<T> results = query.list();
return results;
}
#Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
public PK save(T persistenceObject) {
Serializable save = getSession().save(persistenceObject);
return (PK) save;
}
#Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
public void saveOrUpdate(T persistenceObject) {
getSession().saveOrUpdate(persistenceObject);
}
public void saveOrUpdateBulk(Collection<T> persistenceObject) {
Session session = getOpenSession();
Transaction tx = session.beginTransaction();
int i = 0;
for (Iterator<T> iterator = persistenceObject.iterator(); iterator.hasNext();) {
i++;
session.saveOrUpdate(iterator.next());
if (i % 100 == 0) {
session.flush();
session.clear();
}
}
tx.commit();
session.close();
}
#Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
public boolean delete(PK id) {
Object findById = findById(id);
if (findById != null) {
getSession().delete(findById);
return true;
}
return false;
}
}
AFAIK to remove those extra queries, remove all your modifiers to your #Transactional annotations. The price you pay for restricting your isolation level to READ_COMMITED is that Hibernate will need to perform extra queries to determine if the database is in a dirty state. For 90% of cases, these modifiers are unnecessary. Hibernate is very good at ensuring that your data will be clean without you trying to add these restrictions.
If it is absolutely necessary for you to ensure that your isolation is READ_COMMITTED, you can't do anything about the extra queries.
Moving to a StatelessSession just to get rid of those queries is a bad idea for exactly the reason you pointed out. Really, the only valid reason to be using a StatelessSession is for large batch inserts of data that you know won't be read while the insert is occuring.
pm.detachCopy is working?
I'm making a Spring + ObjectDB(JDO) program.
PersistenceManager#detachCopy returns a transient object despite of #PersistenceCapable:detachable is true.
here is a sample code.
I hava a simple test model(POJO)
#PersistenceCapable(identityType = IdentityType.APPLICATION, detachable="true")
public class TestModel {
#Persistent(valueStrategy=IdGeneratorStrategy.IDENTITY)
#PrimaryKey
private Long id;
#Persistent
private String name;
// getter, setter
}
detachable is set to "true".
and dao is
public class TestModelDaoImpl {
private PersistenceManagerFactory persistenceManagerFactory;
public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
this.persistenceManagerFactory = pmf;
}
public TestModel makePersistent(TestModel obj){
PersistenceManager pm = persistenceManagerFactory.getPersistenceManager();
Transaction tx = pm.currentTransaction();
tx.begin();
pm.makePersistent(obj);
System.out.println(" obj => " + JDOHelper.getObjectState(obj)); // => (1) persistent-new
TestModel detachedObj = pm.detachCopy(obj);
System.out.println(" detachedObj => " + JDOHelper.getObjectState(detachedObj)); // => (2) transient ..
tx.commit();
return detachedObj;
// try catch is omitted
}
}
I think I hava a detached state at (2). but is transient.
Version of ObjectDB is 2.4.0_05
application-context.xml
<bean id="pmf" class="org.springframework.orm.jdo.LocalPersistenceManagerFactoryBean">
<property name="jdoProperties">
<props>
<prop key="javax.jdo.PersistenceManagerFactoryClass">com.objectdb.jdo.PMF</prop>
<prop key="javax.jdo.option.ConnectionURL">$objectdb/db/testdb.odb</prop>
<prop key="javax.jdo.option.ConnectionUserName">admin</prop>
<prop key="javax.jdo.option.ConnectionPassword">admin</prop>
</props>
</property>
</bean>
<bean id="jdoTransactionManager" class="org.springframework.orm.jdo.JdoTransactionManager">
<property name="persistenceManagerFactory">
<ref local="pmfProxy"/>
</property>
</bean>
<bean id="pmfProxy" class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">
<property name="targetPersistenceManagerFactory" ref="pmf"/>
<property name="allowCreate" value="true"/>
</bean>
JDO requires enhancement of all the persistable classes. ObjectDB supports using persistable classes with no enhancement, as an extension to JDO, but not all the JDO features can be supported in that mode.
Particularly, when using instances of non enhanced persistence capable classes, transient and detached objects look the same (since the class is missing the extra fields that are added during enhancement to keep additional information).
Running your test with the TestModel class enhanced provides the expected result:
obj => persistent-new
detachedObj => detached-clean
My validation doesn't seem to be working, the call to hasErrors doesn't return false:
if(bindingResult.hasErrors()) {
...
}
Here is my setup so far:
Using spring mvc, my models module has a Account class:
#Entity
#Table(name = "accounts")
public class Account {
#Id
#GeneratedValue
private int id;
private int rootUserId;
#Size(min=3, max=50, message="Username must be between 3 and 50 characters long.")
private String name;
..
}
My accounts controller has a create action that my form is posting to:
#RequestMapping(value = "/create", method = RequestMethod.POST)
public ModelAndView create(#Valid Account account, BindingResult bindingResult) {
ModelAndView mav = new ModelAndView("accounts/new");
account.setName("a");
if(bindingResult.hasErrors()) {
return mav;
}
mav.setViewName("/test/");
return mav; // TODO should be redirecting, but not working b/c of MaV return value
}
I'm not currently using any of the form helpers in my freemarker markup, and when it hits the controller the Account has not been initialized. So I am just manually setting the name property to "a" for now, which should cause the validation to fail but it doesn't.
My bean is (I think) wired up in my sessionFactory bean here:
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--<property name="packagesToScan" value="com.test.models" />-->
<property name="configLocation" value="/WEB-INF/config/hibernate.cfg.xml"/>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.query.substitutions=true 'Y', false 'N'
hibernate.show_sql=true
hibernate.hbm2ddl.auto=update
</value>
</property>
<property name="annotatedClasses">
<list>
<value>com.test.models.Account</value>
</list>
</property>
</bean>
The actual validation annotations are using javax.validations, my models pom.xml has:
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0-rev-1</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
Why are my validations not being checked?
Is my Account not being picked up by spring for some reason??
P.S: What should the html input look like so that it initalizes the Account object during the post? I have tried:
<input type="texT" ... name="account[name]" />
And also:
name="account.name"
What should it be?
I get this error: No endpoint mapping found for [SaajSoapMessage {http://mycompany/coolservice/specs}ChangePerson]
Following is my ws config file:
<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
<description>An endpoint mapping strategy that looks for #Endpoint and #PayloadRoot annotations.</description>
</bean>
<bean class="org.springframework.ws.server.endpoint.adapter.MarshallingMethodEndpointAdapter">
<description>Enables the MessageDispatchServlet to invoke methods requiring OXM marshalling.</description>
<constructor-arg ref="marshaller"/>
</bean>
<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPaths">
<list>
<value>org.company.xml.persons</value>
<value>org.company.xml.person_allextensions</value>
<value>generated</value>
</list>
</property>
</bean>
<bean id="persons" class="com.easy95.springws.wsdl.wsdl11.MultiPrefixWSDL11Definition">
<property name="schemaCollection" ref="schemaCollection"/>
<property name="portTypeName" value="persons"/>
<property name="locationUri" value="/ws/personnelService/"/>
<property name="targetNamespace" value="http://mycompany/coolservice/specs/definitions"/>
</bean>
<bean id="schemaCollection" class="org.springframework.xml.xsd.commons.CommonsXsdSchemaCollection">
<property name="xsds">
<list>
<value>/DataContract/Person-AllExtensions.xsd</value>
<value>/DataContract/Person.xsd</value>
</list>
</property>
<property name="inline" value="true"/>
</bean>
I have then the following files:
public interface MarshallingPersonService {
public final static String NAMESPACE = "http://mycompany/coolservice/specs";
public final static String CHANGE_PERSON = "ChangePerson";
public RespondPersonType changePerson(ChangePersonType request);
}
and
#Endpoint
public class PersonEndPoint implements MarshallingPersonService {
#PayloadRoot(localPart=CHANGE_PERSON, namespace=NAMESPACE)
public RespondPersonType changePerson(ChangePersonType request) {
System.out.println("Received a request, is request null? " + (request == null ? "yes" : "no"));
return null;
}
}
I am pretty much new to WebServices, and not very comfortable with annotations. I am following a tutorial on setting up jaxb marshaller in springws. I would rather use xml mappings than annotations, although for now I am getting the error message.
EDIT: ChangePersonType
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "ChangePersonType", propOrder = {
"applicationArea",
"dataArea"
})
public class ChangePersonType {
#XmlElement(name = "ApplicationArea", namespace = "http://mycompany/coolservice/specs", required = true)
protected TransApplicationAreaType applicationArea;
#XmlElement(name = "DataArea", namespace = "http://mycompany/coolservice/specs", required = true)
protected DataArea dataArea;
#XmlAttribute(required = true)
#XmlJavaTypeAdapter(NormalizedStringAdapter.class)
protected String releaseID;
#XmlAttribute
#XmlJavaTypeAdapter(NormalizedStringAdapter.class)
protected String versionID;
--The rest are getters and setters.
I solved it. The parameter of the end point class and return variable had to be wrapped in JAXBElement, like JAXBElement.
The reason is
The classes generated by JAXB2 from
your schema come in two flavors: those
that have a #XmlRootElement
annotation, which can be used directly
as either parameter or response, and
those who haven't. Those classes which
haven't got this annotation need to be
wrapped in a JAXBElement.
Besides the generated classes from
your schema, JAXB2 also generates an
ObjectFactory class, which clarifies
the use of JAXBElement. There are some
factory methods is there, which
illustrate how you can use the various
schema types.
Arjen Poutsma
h ttp://forum.springsource.org/showthread.php?t=49817