1

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.

Daniel Arechiga
  • 847
  • 7
  • 19

2 Answers2

2

Okay I finally got it thanks to Jboss docs and this answer: How to exclude Jackson on WildFly 9, I hope this helps in case someone runs into the same issue. (this was on Jboss EAP 7, I seriously think they should upgrade their jackson version)

Refer to Class loading and Modules Jboss EAP 7 on section 3.4 to exclude a module. My jboss-deployment-structure looks like this:

<deployment>
   <exclusions>
   <module name="com.fasterxml.jackson.core.jackson-core" />
   <module name="com.fasterxml.jackson.core.jackson-databind" />
   <module name="com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider" />
   <module name="org.jboss.resteasy.resteasy-jackson2-provider" />
   </exclusions>
</deployment>
Community
  • 1
  • 1
Daniel Arechiga
  • 847
  • 7
  • 19
1

The current (non-accepted) answer is what finally fixed it for me, but I thought I would include a more updated version:

I was attempting to use Jackson 2.9.5 and was getting the noSuchMethodError exception as well. After stumbling across this answer I finally found out that I had to exclude these modules.

Here is what my jboss-deployment-structure.xml file looks like. Note that this is within the /src/main/webapp/WEB-INF folder.

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
    <deployment>
        <exclusions>
            <module name="com.fasterxml.jackson.core.jackson-core"/>
            <module name="com.fasterxml.jackson.core.jackson-databind"/>
            <module name="com.fasterxml.jackson.core.jackson-annotations"/>
            <module name="com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider"/>
            <module name="org.jboss.resteasy.resteasy-jackson-provider"/>
            <module name="org.jboss.resteasy.resteasy-jackson2-provider"/>
        </exclusions>
    </deployment>
</jboss-deployment-structure>
joshft91
  • 1,755
  • 7
  • 38
  • 53