Well, after more than a week of looking for answers, debugging etc. I'm here to ask for help.
Case:
I want to display a LocalDateTime field with format "yyyy-MM-dd'T'HH:mm:ss", I've read about support for this using jackson-datatype-jsr310
, however when including jsr310
dependency I get this exception thrown anywhere there's a DateTime
type:
java.lang.NoSuchMethodError: com.fasterxml.jackson.datatype.jsr310.ser.JSR310FormattedSerializerBase.findFormatOverrides(Lcom/fasterxml/jackson/databind/SerializerProvider;Lcom/fasterxml/jackson/databind/BeanProperty;Ljava/lang/Class;)Lcom/fasterxml/jackson/annotation/JsonFormat$Value;
I've read that it has to do with version incompatibility with spring and jackson-datatype-jsr310
so I'm managing all my dependencies with spring-boot-dependencies
; I even surfed into the artifact's pom and effectively jackson-datatype-jsr310 is listed there, now before you suggest removing jsr310 dependency, let me say I've already tried that and whenever I do that I can't register JavaTimeModule
in my ObjectMapper
, and if I don't register the module I get the DateTime object serialized in a very unconventional way (no format, just an object with properties for days, minutes months year etc). I've tried playing with different properties in the ObjectMapper configuration and nothing has got rid of that error but removing jsr310 dependency, I've also tried different versions of that dependency and nothing works. Please help me out.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.faintness</groupId>
<artifactId>FaintnessOnlineStore</artifactId>
<packaging>war</packaging>
<version>1</version>
<name>FaintnessOnlineStore Maven Webapp</name>
<url>http://maven.apache.org</url>
<!-- PROPERTIES -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- <springsecurity.version>4.0.1.RELEASE</springsecurity.version>-->
<plugin.war.warName>${project.build.finalName}</plugin.war.warName>
<maven.test.skip>true</maven.test.skip>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.4.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<!-- all spring security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<!-- <version>${springsecurity.version}</version> -->
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<!-- <version>${springsecurity.version}</version> -->
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<!-- <version>${springsecurity.version}</version> -->
</dependency>
<!-- basic spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<!-- <version>4.3.7.RELEASE</version> -->
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<!-- <version>4.3.7.RELEASE</version> -->
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<!-- <version>4.3.7.RELEASE</version> -->
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<!-- <version>4.3.7.RELEASE</version> -->
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<!-- <version>4.3.7.RELEASE</version> -->
</dependency>
<!-- spring web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<!-- <version>4.3.7.RELEASE</version> -->
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<!-- <version>4.3.7.RELEASE</version> -->
</dependency>
<dependency>
<groupId>org.springframework.mobile</groupId>
<artifactId>spring-mobile-device</artifactId>
<!-- <version>1.1.5.RELEASE</version> -->
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
<!-- Serialization -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<!-- <version>${jackson.version}</version> -->
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-csv</artifactId>
<!-- <version>${jackson.dataformat.csv.version}</version> -->
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<!-- <version>3.6.8.Final</version> -->
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
<!-- JUnit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<!-- <version>4.3.7.RELEASE</version> -->
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<!-- <version>5.2.4.Final</version> -->
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<!-- <version>3.0.1-b08</version> -->
</dependency>
<!-- extra -->
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.6</version>
</dependency>
<!-- Support for LocalDateTime and ZonedDateTime data conversion in SQL -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-java8</artifactId>
<!-- <version>5.0.4.Final</version> -->
</dependency>
</dependencies>
<build>
<finalName>FaintnessOnlineStore</finalName>
<!-- PLUGINS -->
<plugins>
<!-- configure WAR stuff etc -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<filteringDeploymentDescriptors>true</filteringDeploymentDescriptors>
<warName>${plugin.war.warName}</warName>
</configuration>
</plugin>
<!-- this is important!! -->
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!-- jboss plugin important too!! -->
<plugin>
<groupId>org.jboss.as.plugins</groupId>
<artifactId>jboss-as-maven-plugin</artifactId>
<version>7.9.Final</version>
<configuration>
<filename>${project.artifactId}-${project.version}.ear</filename>
<port>8999</port> <!-- you change it following what you have on your server config -->
<filename>${plugin.war.warName}.${project.packaging}</filename>
</configuration>
</plugin>
</plugins>
</build>
</project>
ObjectMapper
package com.pier.config;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
@Component
public class SpecObjectMapper extends ObjectMapper{
public SpecObjectMapper(){
registerModule(new JavaTimeModule() );
configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,true)
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
}
}
WebConfiguration
package com.pier.config;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.annotation.PropertySource;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.mobile.device.DeviceWebArgumentResolver;
import org.springframework.mobile.device.site.SitePreferenceWebArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.ServletWebArgumentResolverAdapter;
@EnableWebMvc
@Configuration
@ComponentScan(basePackages={"com.pier.controllers.*", "com.pier.config, com.pier.model.security", "com.pier.rest,com.pier.security.*"})
public class WebConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/pages/**")
.addResourceLocations("/pages/");
}
@Override
public void addArgumentResolvers(
List<HandlerMethodArgumentResolver> argumentResolvers) {
// Adding Spring mobile argument resolvers
argumentResolvers.add(
new ServletWebArgumentResolverAdapter(
new DeviceWebArgumentResolver()));
argumentResolvers.add(
new ServletWebArgumentResolverAdapter(
new SitePreferenceWebArgumentResolver()));
}
@Autowired
SpecObjectMapper domainMapper;
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters)
{
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(domainMapper);
converters.add(converter);
super.configureMessageConverters(converters);
}
}
The entity to serialize
@Entity
@Table(name="PROMOTION")
public class Promotion implements ObjectModel<Long>{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@Column(name="DISPLAY_NAME",length=30)
@Size(min=5,max=30)
private String displayName;
@Column(name = "START_DATE")
@Type(type="org.hibernate.type.ZonedDateTimeType")
private ZonedDateTime startDate;
@Column(name = "END_DATE")
@Type(type="org.hibernate.type.ZonedDateTimeType")
private ZonedDateTime endDate;
Update:
I got another clue and got this on the console: ModuleClassLoader for Module "com.fasterxml.jackson.core.jackson-databind:main" from local module loader @15b3e5b (finder: local module finder @61ca2dfa (roots: C:\Users\PC\EAP-7.0.0\modules,C:\Users\PC\EAP-7.0.0\modules\system\layers\base))
So now I know what's going on, the version is outdated in jboss modules, I need to exclude it or find a way to load it from my classpath rather than the module.