jackson serialize lazy object HttpMessageNotWritableException & LazyInitializationException - java

This is a follow up questions from this:
Spring Hibernate FetchType LazyInitializationException even when not calling association
I have tried to implement this solution but with no luck. I am wondering if I have made a mistake some where...
Avoid Jackson serialization on non fetched lazy objects
applicationContext.xml
<context:annotation-config />
<context:component-scan base-package="com.app"></context:component-scan>
<tx:annotation-driven />
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="com.app.service.HibernateAwareObjectMapper" />
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!-- Hibernate server settings -->
HibernateAwareObjectMapper
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.hibernate4.Hibernate4Module;
public class HibernateAwareObjectMapper extends ObjectMapper {
public HibernateAwareObjectMapper() {
Hibernate4Module hm = new Hibernate4Module();
registerModule(hm);
}
}
pom.xml
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.11.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.3.2.Final</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate4</artifactId>
<version>2.8.6</version>
</dependency>
And I am still getting the following error
Hibernate: select this_.person_id as person_i1_1_0_, this_.age as age2_1_0_, this_.name as name3_1_0_ from person this_
[Person [person_id=1, name=eric, age=11]]
Jun 20, 2017 12:37:29 AM org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver handleHttpMessageNotWritable
WARNING: Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: failed to lazily initialize a collection of role: com.app.person.Person.phones, could not initialize proxy - no Session (through reference chain: java.util.HashMap["results"]->java.util.ArrayList[0]->com.app.person.Person["phones"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException:
Please any insight or suggestions are much appreciated...
One last thing, I don't want to marke it as JsonIgnore, as it will never be serialized. There will be times where I will need to retrieve the Lazy object.
Thank you

to resolve this probleme there two ways. the first one is to ignore the phones if you don't need this information in this request by using #JsonIgnore.
the second way is the load the phones before closing the transaction. and to do that you can use Hibernate.initialize(person.getPhones()). Or you can fetch this collection using #OneToMany(fetch = FetchType.EAGER) on the collection.

Related

Wildfly 10 Infinispan JCache: #CacheResult causes "Member of array type or annotation type must be annotated #NonBinding"

I'm trying to use the Infinispan JCache annotations within Wilfly 10. My Wildfly installation has the Wildfly-Camel extension (http://wildfly-extras.github.io/wildfly-camel/).
I would like to use method level caching:
#CacheResult
public Connector getConnector(String name) {
...
}
Relevant Maven dependencies of my app:
<dependencies>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-jcache</artifactId>
<version>8.2.4.Final</version>
<scope>provided</scope>
</dependency>
</dependencies>
My beans.xml:
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.2" bean-discovery-mode="annotated">
<interceptors>
<class>org.infinispan.jcache.annotation.InjectedCacheResultInterceptor</class>
<class>org.infinispan.jcache.annotation.InjectedCachePutInterceptor</class>
<class>org.infinispan.jcache.annotation.InjectedCacheRemoveEntryInterceptor</class>
<class>org.infinispan.jcache.annotation.InjectedCacheRemoveAllInterceptor</class>
<class>org.infinispan.jcache.annotation.CacheResultInterceptor</class>
<class>org.infinispan.jcache.annotation.CachePutInterceptor</class>
<class>org.infinispan.jcache.annotation.CacheRemoveEntryInterceptor</class>
<class>org.infinispan.jcache.annotation.CacheRemoveAllInterceptor</class>
</interceptors>
</beans>
However, I get the following error, when the application is being deployed:
WELD-001121: Member of array type or annotation type must be annotated #NonBinding: [EnhancedAnnotatedMethodImpl] public abstract javax.cache.annotation.CacheResult.cachedExceptions()
Which is strange as all methods in javax.cache.annotation.CacheResult are annotated with #Nobinding
Any ideas?
Thank you!
Have you tested behavior removing bean-discovery-mode="annotated" from beans.xml?
Have you assigned a cacheName to #CacheResult annotation?
It would be good to enable TRACE debug in standalone.xml to "org.infinispan"
I have it running with "bean-discovery-mode=all" (if not specified in beans.xml, takes this as default) and indicating only the last four interceptor classes: org.infinispan.jcache.annotation.Cache*
Hope it helps, keep posted.

com.sun.xml.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl cannot be cast to javax.xml.soap.MessageFactory

I'm using WebLgic have the following saaj soap message factory. I've tried leaving off the messageFactory and just the soapVersion and vice Versa. I've also tried the different messageFactory Impl beans that are commented out. I'm still getting the error in the title. Why is t trying to use version 1.1?
<bean id="saajMessageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
<property name="messageFactory">
<bean class="com.sun.xml.messaging.saaj.soap.MessageFactoryImpl"
/>
<!-- <bean class="com.sun.xml.messaging.saaj.soap.ver1_2.SOAPMessageFactory1_2Impl"
/> -->
<!-- <bean class="weblogic.xml.saaj.MessageFactoryImpl"/> -->
</property>
<property name="soapVersion">
<util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_12" />
</property>
</bean>
Error:
SAAJ MessageFactory: Unable to create message factory for SOAP: com.sun.xml.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl cannot be cast to javax.xml.soap.MessageFactory; nested exception is javax.xml.soap.SOAPException: Unable to create message factory for SOAP: com.sun.xml.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl cannot be cast to javax.xml.soap.MessageFactory
at org.springframework.ws.support.DefaultStrategiesHelper.instantiateBean(DefaultStrategiesHelper.java:188)
at org.springframework.ws.support.DefaultStrategiesHelper.getDefaultStrategies(DefaultStrategiesHelper.java:134)
at org.springframework.ws.support.DefaultStrategiesHelper.getDefaultStrategy(DefaultStrategiesHelper.java:219)
at org.springframework.ws.support.DefaultStrategiesHelper.getDefaultStrategy(DefaultStrategiesHelper.java:203)
at org.springframework.ws.client.core.WebServiceTemplate.initMessageFactory(WebServiceTemplate.java:310)
pom file:
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.messaging.saaj</groupId>
<artifactId>saaj-impl</artifactId>
<version>1.3.15</version>
</dependency>
<dependency>
<groupId>javax.xml.soap</groupId>
<artifactId>saaj-api</artifactId>
<version>1.3.5</version>
</dependency>
Weblogic.xml:
<prefer-application-packages>
<package-name>javax.xml.soap.*</package-name>
<package-name>javax.xml.ws.*</package-name>
<package-name>com.sun.xml.messsaging.saaj.*</package-name>
</prefer-application-packages>
I should also add that I tried setting various this JVM argument with various options: -Djavax.xml.soap.MessageFactory=weblogic.xml.saaj.MessageFactoryImpl
such as com.sun.xml.messaging.saaj.soap.ver1_2.SOAPMessageFactory1_2Impl. The error message now reflects the new Impl class, but I still can't get around the error.
I'm not sure exactly what ended up fixing this issue, but I was also getting some other errors as I tried different things, and I finally got everything working as specified in this post: java.lang.NoClassDefFoundError: org/apache/cxf/jaxrs/impl/UriBuilderImpl. I ended up removing those pom file entries above.
One thing I did have to do was to download a new version of Maven as the one that came in my VM was giving me problems.

DataNucleus / Kundera with HBase with ElementCollection - Unable to find the object with a null id

To start with, I use HBase 0.94.5 (also tried 0.92.2 with the same results).
I have a situation like this:
Variable class:
#Entity
#Table(name = "variable", schema = "keyspace#hbase-pu")
public class Variable {
#Id
private String Id;
#Column(name = "Name")
private String Name;
#ElementCollection(fetch = FetchType.EAGER)
//#CollectionTable(name = "datavalues") // Doesn't work with or without.
private List<DataValue> DataValues;
// Getters and setters omitted.
}
DataValue class:
#Embeddable
public class DataValue {
#Column(name = "Value")
private Object Value;
// Getters and setters omitted.
}
Now, storing this is no problem at all, but when I want to retrieve it, boom goes the dynamite. This exception is thrown:
Caused by: org.datanucleus.exceptions.NucleusUserException: Unable to find the object with a null id!
Exception in thread "main" javax.persistence.PersistenceException: Unable to find the object with a null id!
at org.datanucleus.api.jpa.NucleusJPAHelper.getJPAExceptionForNucleusException(NucleusJPAHelper.java:414)
at org.datanucleus.api.jpa.JPAQuery.getResultList(JPAQuery.java:203)
at Main.main(Main.java:73)
Caused by: org.datanucleus.exceptions.NucleusUserException: Unable to find the object with a null id!
at org.datanucleus.ExecutionContextImpl.findObject(ExecutionContextImpl.java:3441)
at org.datanucleus.store.hbase.fieldmanager.FetchFieldManager.fetchObjectField(FetchFieldManager.java:287)
at org.datanucleus.state.JDOStateManager.replacingObjectField(JDOStateManager.java:2178)
at Variable.jdoReplaceField(Variable.java)
at Variable.jdoReplaceFields(Variable.java)
at org.datanucleus.state.JDOStateManager.replaceFields(JDOStateManager.java:3415)
at org.datanucleus.state.JDOStateManager.replaceFields(JDOStateManager.java:3442)
at org.datanucleus.store.hbase.query.HBaseQueryUtils$2.fetchFields(HBaseQueryUtils.java:270)
at org.datanucleus.state.JDOStateManager.loadFieldValues(JDOStateManager.java:2547)
at org.datanucleus.state.JDOStateManager.initialiseForHollow(JDOStateManager.java:298)
at org.datanucleus.state.ObjectProviderFactoryImpl.newForHollow(ObjectProviderFactoryImpl.java:89)
at org.datanucleus.ExecutionContextImpl.newObjectProviderForHollowPopulated(ExecutionContextImpl.java:1237)
at org.datanucleus.ExecutionContextImpl.findObject(ExecutionContextImpl.java:3053)
at org.datanucleus.store.hbase.query.HBaseQueryUtils.getObjectUsingApplicationIdForResult(HBaseQueryUtils.java:265)
at org.datanucleus.store.hbase.query.HBaseQueryUtils.getObjectsOfType(HBaseQueryUtils.java:194)
at org.datanucleus.store.hbase.query.HBaseQueryUtils.getObjectsOfCandidateType(HBaseQueryUtils.java:93)
at org.datanucleus.store.hbase.query.JPQLQuery.performExecute(JPQLQuery.java:327)
at org.datanucleus.store.query.Query.executeQuery(Query.java:1786)
at org.datanucleus.store.query.Query.executeWithMap(Query.java:1690)
at org.datanucleus.api.jpa.JPAQuery.getResultList(JPAQuery.java:186)
... 1 more
This is because of the ElementCollection, as when I remove this it retreives the variable class perfectly from HBase. I also tried Kundera 2.4 (same example code), which is a lot easier to setup than this DataNucleus 'enhance' thing, but it throws something with a Stream exception. Both sites show code samples similar to my code above, so I'm very curious to what I'm doing wrong here.
Relevant pom.xml:
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jpa_2.0_spec</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>javax.jdo</groupId>
<artifactId>jdo-api</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-core</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-api-jpa</artifactId>
<version>3.2.0-release</version>
</dependency>
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-hbase</artifactId>
<version>3.2.0-release</version>
</dependency>
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-enhancer</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-core</artifactId>
<version>1.1.2</version>
<exclusions>
<exclusion>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
</exclusion>
<exclusion>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase</artifactId>
<version>0.94.5</version>
</dependency>
<plugin>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-maven-plugin</artifactId>
<version>3.2.0-release</version>
<configuration>
<api>JPA</api>
<persistenceUnitName>hbase-pu</persistenceUnitName>
<verbose>true</verbose>
</configuration>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>enhance</goal>
</goals>
</execution>
</executions>
</plugin>
persistance.xml for DataNucleus:
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">
<!-- JPA tutorial "unit" -->
<persistence-unit name="hbase-pu" transaction-type="RESOURCE_LOCAL">
<provider>org.datanucleus.api.jpa.PersistenceProviderImpl</provider>
<class>Variable</class>
<class>DataValue</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="datanucleus.storeManagerType" value="hbase" />
<property name="datanucleus.ConnectionURL" value="hbase:localhost:2281"/>
<property name="datanucleus.ConnectionUserName" value=""/>
<property name="datanucleus.ConnectionPassword" value=""/>
<property name="datanucleus.autoCreateSchema" value="true"/>
<property name="datanucleus.autoCreateTables" value="true" />
<property name="datanucleus.autoCreateColumns" value="true" />
<property name="datanucleus.validateTables" value="true"/>
<property name="datanucleus.validateConstraints" value="false"/>
<property name="datanucleus.Optimistic" value="false"/>
<property name="datanucleus.Multithreaded" value="true" />
</properties>
</persistence-unit>
</persistence>
persistence.xml for Kundera:
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
https://raw.github.com/impetus-opensource/Kundera/Kundera-2.0.4/kundera-core/src/test/resources/META-INF/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="hbase-pu">
<provider>com.impetus.kundera.KunderaPersistence</provider>
<properties>
<property name="kundera.nodes" value="localhost" />
<property name="kundera.port" value="2182" />
<property name="kundera.keyspace" value="keyspace" />
<property name="kundera.dialect" value="hbase" />
<property name="kundera.client.lookup.class" value="com.impetus.client.hbase.HBaseClientFactory" />
<property name="kundera.cache.provider.class" value="com.impetus.kundera.cache.ehcache.EhCacheProvider" />
<property name="kundera.cache.config.resource" value="/ehcache-test.xml" />
<property name="kundera.ddl.auto.prepare" value="update" />
</properties>
</persistence-unit>
</persistence>
I'm kinda shooting blanks here with this whole thing and I have a feeling I pretty much tried everything at this moment and have no idea how to continue.
-- See comment below.
New Variable class:
#Entity
#Table(name = "variable", schema = "keyspace#hbase-pu")
public class Variable {
#Id
private String Id;
#Column(name = "Name")
private String Name;
#ElementCollection(fetch = FetchType.EAGER)
private List<Object> DataValues;
#Column(name = "Value")
#Lob
private Object Value;
// Getters and setters omitted.
}
So you want to have an embedded collection ? But then as this page shows clearly enough, this is not supported for HBase at the moment (supported for MongoDB, but then that has a much more flexible datastore structure to allow it). You can have a Collection of non-Entities (persisted into the same HTable as the owner), and you can have a Collection of (non-embedded) Entities, but not an embedded Collection. Obviously you could contribute your time to provide support for that should it be important to you (and I'll even provide you with starting points in the code to look at).
No reason why "CollectionTable" should make a difference ... it's an annotation for RDBMS for the schema (but then JPA is designed solely for RDBMS).
PS 1, this "enhance thing" is as simple as adding the "plugin" block to pom.xml. So unless you're prepared to express to the DataNucleus project what your difficulty with it is, then how can they know it.
PS 2, if reporting a problem I'd expect you to show the exception + stack trace no matter what software is involved, because from an exception message you tell people very little.

Upgrading Spring Security 2.5 to 3.1 - java.lang.NoClassDefFoundError: org/springframework/security/Authentication

This problem is proving very tricky to resolve. Usual story, inherited a very poorly maintained java web application with no unit tests and a variety of ancient jar dependencies with no version info dumped in a lib directory built using Ant. In order to get better maintenance and understanding of the dependencies I migrated over to Maven. Subsequently, I realised the version of Spring was quite old (Spring 2.x and Spring Security 2.0.3). I upgraded successfully to Spring 2.5. I have now started migrating Spring up to 3.1.2.RELEASE, and Spring Security up to 3.1.3.RELEASE.
Everything compiles, I don't get any namespace issues either (declared in headers of Spring XML configs), but fails when being deployed as a WAR file into Tomcat Container. The log file reports:
Could not instantiate bean class [com.mydomain.repository.ReportDaoImpl]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/springframework/security/Authentication
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:997)
I checked, and org.springframework.security.Authentication belongs to the old Spring Security jar (2.0.4)
My current Maven dependencies are as follows:
<spring.version>3.1.2.RELEASE</spring.version>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- SPRING SECURITY -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-acl</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
My security.xml is minimal:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<http auto-config='true'>
<intercept-url pattern="/**" access="ROLE_Admin" />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="admin" password="password" authorities="ROLE_Admin" />
</user-service>
</authentication-provider>
</authentication-manager>
All my other Spring Config files use the following namespace headers in their configs:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
As far as I know this application contains NO annotations regarding Spring.
So how does the Spring Security 2.0.4 class org.springframework.security.Authentication get requested by a Spring 3.1 class org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory when instantiating a DAO object (which has nothing to do with Spring security settings). It may be that the DAO is picked because it is the first bean in order to get instantiated in the applicationContext.xml by the classloader (via Spring dependency injection container) but i cannot see how there is still a reference lurking somewhere in this application to an old 2.0.4 class. Since everything compiles ok, and the Maven pom only references 3.1 my take is that there must be some configuration somewhere still trying to pull in an old class. Anyone with Spring Security knowledge (in particular upgrading a large app from a version 2 to version 3) might have hit this problem before but I couldn't find exact match via google. Thanks for any suggestions on this. Currently stumped.
Quick update:
The applicationContext.xml has the namespace header as given above and the DAO is simply referenced as follows:
<bean id="reportDao" class="com.mydomain.repository.ReportDaoImpl">
<property name="dataSource" ref="myDataSource" />
</bean>
There is really nothing more to it. The applicationContext pulls in another context file applicationContext-datasource which declares (same namespace header again as above):
<bean id="parentDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
</bean>
<bean id="myDataSource" parent="parentDataSource">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
The ReportDao is over 1500 lines of poorly written procedural code. It is a POJO and implements rg.springframework.context.ApplicationContextAware. It also uses org.springframework.jdbc.core.support.JdbcDaoSupport for performing CRUD operations to the database.
Running mvn -X the output for dependencies (have switched to Spring [main] 3.0.7):
org.springframework:spring-webmvc:jar:3.0.7.RELEASE:compile
org.springframework:spring-asm:jar:3.0.7.RELEASE:compile
org.springframework:spring-beans:jar:3.0.7.RELEASE:compile
org.springframework:spring-expression:jar:3.0.7.RELEASE:compile
org.springframework:spring-web:jar:3.0.7.RELEASE:compile
org.springframework:spring-aop:jar:3.0.7.RELEASE:compile
aopalliance:aopalliance:jar:1.0:compile
org.springframework:spring-context:jar:3.0.7.RELEASE:compile
org.springframework:spring-context-support:jar:3.0.7.RELEASE:compile
org.springframework:spring-core:jar:3.0.7.RELEASE:compile
org.springframework:spring-tx:jar:3.0.7.RELEASE:compile
org.springframework:spring-jdbc:jar:3.0.7.RELEASE:compile
org.springframework.security:spring-security-acl:jar:3.1.3.RELEASE:compile
org.springframework.security:spring-security-config:jar:3.1.3.RELEASE:compile
org.springframework.security:spring-security-core:jar:3.1.3.RELEASE:compile
org.springframework.security:spring-security-taglibs:jar:3.1.3.RELEASE:compile
org.springframework.security:spring-security-web:jar:3.1.3.RELEASE:compile
org.springframework.security:spring-security-crypto:jar:3.1.3.RELEASE:compile
Looks ok I believe.
The only spring jars (grepped to be certain) in the WEB-INF/lib directory of the deliverable WAR file are:
./spring-aop-3.0.7.RELEASE.jar
./spring-asm-3.0.7.RELEASE.jar
./spring-beans-3.0.7.RELEASE.jar
./spring-context-3.0.7.RELEASE.jar
./spring-context-support-3.0.7.RELEASE.jar
./spring-core-3.0.7.RELEASE.jar
./spring-expression-3.0.7.RELEASE.jar
./spring-jdbc-3.0.7.RELEASE.jar
./spring-security-acl-3.1.3.RELEASE.jar
./spring-security-config-3.1.3.RELEASE.jar
./spring-security-core-3.1.3.RELEASE.jar
./spring-security-crypto-3.1.3.RELEASE.jar
./spring-security-taglibs-3.1.3.RELEASE.jar
./spring-security-web-3.1.3.RELEASE.jar
./spring-tx-3.0.7.RELEASE.jar
./spring-web-3.0.7.RELEASE.jar
./spring-webmvc-3.0.7.RELEASE.jar
Again, looks sensible.
Grepping the source code for "Authentication" did not help. This looks like a transitive runtime dependency issue. It goes unnoticed at compilation and isn't declared anywhere as a first level dependency. But somehow at runtime (in the Tomcat 6 container) when deployed a rogue reference to an old library file is requested.
Going to delete my Tomcat instance and start from scratch just as a precaution.
Ok, finally solved this particular problem. NoClassDefFoundError is exactly what it says on the tin. As Luke Taylor asked "Are you absolutely sure you recompiled?" Well, yes and no. I definitely recompiled, cleaned target (using Maven) etc. And the first time I used a decompiler to see the source for the generated class "XXXDao" I saw my changes. But I also noticed that when I added / removed a couple of lines from the java source, the error in the stacktrace remained on the same (random) line number. That explained I was getting a stale .class file somehow. Turns out, Maven and / or Eclipse (m2eclipse plugin) somehow managed to compile class files into the WEB-INF/classes directory of my core project (not target) and was non-deterministically overwriting the WEB-INF/classes directory in target with some classes. Even stranger, it ALWAYS deployed the old classes when compressing the classes into .WAR. So you have a case of the exploded contents looking correct but actually the compresssed WAR file with different classes.
Lesson learnt - if you get this sort of behaviour, double check the compilation steps, and try to find out how perhaps an old class file (referencing the old Authentication class) has gotten into your new build. Thanks for the pointers from those that contributed to the post!

Spring REST XML service not accepting XML as "accept" header

I have several REST services defined that are currently returning JSON formatted objects as service response bodies. I'm trying to make this service also accept XML as a new requirement though it does not accept this.
I'm following the spring-mvc-showcase sample project and have setup my pom.xml dependencies almost identically, my service definitions likewise are very simple.
#Controller
#RequestMapping(value = "api/sales/*")
public class SalesController {
#RequestMapping(value = "/countries", method = RequestMethod.GET)
#ResponseBody
public List<NamedEntity> getCountries() {
NamedEntity has the appropriate #XmlRootElement annotation.
Could somebody explain the most basic requirements that I would need to get XML as a ResponseBody that the spring-mvc-showcase sample project is using.
EDIT: Added spring MVC sample.
The sample from the spring-mvc-showcase is as follows:
package org.springframework.samples.mvc.messageconverters;
#Controller
#RequestMapping("messageconverters/*")
public class MessageConvertersController {
#RequestMapping(value="/xml", method=RequestMethod.GET)
public #ResponseBody JavaBean writeXml() {
return new JavaBean("bar", "fruit");
Check the request header, client needs to have "application/xml" in the header, rather than "application/json "
Having said this make sure you have registered appropriate message converter for your object. If you are using Java 6 then Spring will auto detect JAXB in your classpath or else you can manually add the converter.
Add #Produces("application/xml") to getCountries()
You need to send "application/xml", not "application/application+xml". Also consider using:
#RequestMapping(value = "/countries", method = RequestMethod.GET, produces={"application/json", "application/xml"})
This ensures your method responds to those media types only and rejects others with 406 HTTP status code.
try this dispatcher servlet config.
<mvc:annotation-driven
content-negotiation-manager="contentManager" />
<bean id="contentManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false" />
<property name="ignoreAcceptHeader" value="false" />
<property name="defaultContentType" value="application/json" />
<property name="useJaf" value="false" />
</bean>
and some dependency
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.4.3</version>
</dependency>

Categories