0

I am learning Spring Framework and the first goal for me is to return an Version object using a built in serializer.

public class Version {
    private int build;
    private String releaseType;

    public Version(int build, String releaseType) {
        this.build          = build;
        this.releaseType    = releaseType;
    }

    public int getBuild() {
        return build;
    }

    public String getReleaseType() {
        return releaseType;
    }

    public void setBuild(int build) {
        this.build = build;
    }

    public void setReleaseType(String releaseType) {
        this.releaseType = releaseType;
    }
}

And my root class (I called it Kernel), would love to stay with application configuration using one class

@EnableWebMvc
@Configuration
public class Kernel extends AbstractDispatcherServletInitializer implements WebMvcConfigurer {
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext annotationConfigWebApplicationContext = new AnnotationConfigWebApplicationContext();
        annotationConfigWebApplicationContext.register(VersionController.class);

        return annotationConfigWebApplicationContext;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/*" };
    }

    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(new MappingJackson2HttpMessageConverter());
    }
}

The controller

@RestController
public class VersionController {
    @RequestMapping("/version")
    @ResponseBody
    public Version getVersion() {
        return new Version(192837, "DEV");
    }
}

I am trying to go as simple as I can, I don't have any XML file in my project as I want to go fully Annotation & Java mode as long as I can.

I never really liked the XML driven concept in Spring Framework as most of time the content of these XML files looks like exposed programmer garbage that nobody but owner would understand how to setup. What is the point of exposing configuration for response serializers as deployment worker will have no clue what is that.

The error I got is:

HTTP Status 500 – Internal Server Error, No converter found for return value of type

I suspect that the Jackson is not called because Spring does not know that he is expected to use it on Version object, but I have no idea how to force Spring to do it.

My pom.xml just for sure (using Tomcat9 as web server)

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>pl.protean.league-craft</groupId>
    <artifactId>league-craft</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.8</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.2.2</version>
                <configuration>
                    <warName>lc</warName>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer
                                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>Kernel</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>
Bartłomiej Sobieszek
  • 2,692
  • 2
  • 25
  • 40

1 Answers1

0

I solved my issue thanks to this answer https://stackoverflow.com/a/10650452/2010246

A

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.add(new MappingJackson2HttpMessageConverter());
}

Will not work just like that even if I am overriding this method in AbstractDispatcherServletInitializer

Instead of that I had to create separate class for MVC configuration

package configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import java.util.List;

@Configuration
public class Mvc extends WebMvcConfigurationSupport {
    protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(converter());
        addDefaultHttpMessageConverters(converters);
    }

    @Bean
    MappingJackson2HttpMessageConverter converter() {
        return new MappingJackson2HttpMessageConverter();
    }
}

Now it loads correctly and I can simply return the class like I wanted to

I guess the core problem was there were no class that is annotated as @Configuration and extends the WebMvcConfigurationSupport parent

Bartłomiej Sobieszek
  • 2,692
  • 2
  • 25
  • 40