POST error 500 - jersey 2 rest api application - rest

Problem
I have a simple rest application with low complexity built using jersey 2. I use maven for dependency management. I was getting cors issue with post request(JSON) from angular app. It was working fine with other content type except for json payloads. requests with json data was working fine in postman. Then I created a CORSFilter. Now the error is changed and everything is stopped working.
I need
to find whether my project setup is correct or not
to find what the blunder I have done
send post request from angular app with json data and get response
Project deployment assembly
https://imgur.com/a/TolLvEJ
Project facets
https://imgur.com/a/Eqga93Z
My project structure
https://imgur.com/a/VZMP5Vu
I have followed so many suggestions and workarounds. Maybe I was wrongly following them.
My 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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>OnlineOrganicMarket</groupId>
<artifactId>OnlineOrganicMarket</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>11</release>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.1</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<jersey2.version>2.27</jersey2.version>
<jaxrs.version>2.1</jaxrs.version>
</properties>
<dependencies>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>6.2.1</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20160810</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<!-- JAX-RS -->
<dependency> <groupId>javax.ws.rs</groupId> <artifactId>javax.ws.rs-api</artifactId>
<version>${jaxrs.version}</version> </dependency>
<!-- Jersey 2.19 -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey2.version}</version>
</dependency>
<!-- <dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-server</artifactId>
<version>${jersey2.version}</version> </dependency> <dependency> <groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId> <version>${jersey2.version}</version>
</dependency> -->
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>${jersey2.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>2.26-b03</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-json-org</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.5.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
</dependencies>
</project>
My web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>OnlineOrganicMarket</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.oom.services</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
<!-- <servlet>
<description>JAX-RS Tools Generated - Do not modify</description>
<servlet-name>JAX-RS Servlet</servlet-name>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS Servlet</servlet-name>
<url-pattern>/jaxrs/*</url-pattern>
</servlet-mapping> -->
</web-app>
CORS filter
package com.oom.services.filter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.annotation.Priority;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import org.glassfish.jersey.server.ExtendedUriInfo;
#Provider
#Priority(Priorities.HEADER_DECORATOR)
public class CORSFilter implements ContainerRequestFilter, ContainerResponseFilter {
private static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
private static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";
private static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods";
private static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
private static final String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers";
private static final String AUTHORIZATION = "authorization";
private static final String ORIGIN = "Origin";
private static String extractAllowedMethods(final ExtendedUriInfo extendedUriInfo) {
final Optional<Class<?>> optional = extendedUriInfo.getMatchedRuntimeResources().stream()
.flatMap(r -> r.getResources().stream()).flatMap(r -> r.getHandlerClasses().stream())
.filter(r -> r.getPackage().getName().startsWith("com.oom.services")).findFirst();
if (optional.isPresent()) {
return Arrays.stream(optional.get().getDeclaredMethods())//
.flatMap(m -> Arrays.stream(m.getAnnotations()))//
.map(a -> a.annotationType().getAnnotation(javax.ws.rs.HttpMethod.class))//
.filter(Objects::nonNull)//
.map(HttpMethod::value)//
.distinct()//
.collect(Collectors.joining(", "));
}
// Returning OPTIONS is a bit shady, as ACAM is about *real*, actual methods only.
return "OPTIONS";
}
#Context
private HttpServletRequest request;
#Context
private ExtendedUriInfo extendedUriInfo;
#Override
public void filter(final ContainerRequestContext requestContext) throws IOException {
final String origin = requestContext.getHeaderString(ORIGIN);
if (origin != null && "OPTIONS".equals(requestContext.getMethod())) {
request.setAttribute(this.getClass().getName(), true);
requestContext.abortWith(Response.ok("CORS OK, carry on.", MediaType.TEXT_PLAIN_TYPE).build());
}
}
/**
* #see https://www.w3.org/TR/cors/
* #see https://jmchung.github.io/blog/2013/08/11/cross-domain-on-jersey-restful-web-services/
* #see https://solutionsisee.wordpress.com/2016/06/30/adding-cors-support-in-jersey-server/
*/
#Override
public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext)
throws IOException {
final MultivaluedMap<String, Object> responseHeaders = responseContext.getHeaders();
final String origin = requestContext.getHeaderString(ORIGIN);
if (origin != null) {
// The presence of the Origin header marks a CORS request.
responseHeaders.add(ACCESS_CONTROL_ALLOW_ORIGIN, origin);
responseHeaders.add(ACCESS_CONTROL_ALLOW_METHODS, extractAllowedMethods(extendedUriInfo));
responseHeaders.add(ACCESS_CONTROL_ALLOW_HEADERS, AUTHORIZATION + ", X-Requested-With, Content-Type");
if (requestContext.getHeaderString(ACCESS_CONTROL_REQUEST_HEADERS) != null) {
responseHeaders.add(ACCESS_CONTROL_ALLOW_CREDENTIALS, requestContext
.getHeaderString(ACCESS_CONTROL_REQUEST_HEADERS).toLowerCase().contains(AUTHORIZATION));
}
}
if (request.getAttribute(this.getClass().getName()) != null) {
// We are in a CORS Preflight answer, fast tracked. The entity (== response body) is not
// relevant.
}
}
}
Currently getting this error
<!doctype html><html lang="en"><head><title>HTTP Status 500 – Internal Server Error</title><style type="text/css">h1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} h2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} h3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} body {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} b {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} p {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;} a {color:black;} a.name {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 500 – Internal Server Error</h1><hr class="line" /><p><b>Type</b> Exception Report</p><p><b>Message</b> org.glassfish.jersey.server.ContainerException: java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/filter/TokenFilter</p><p><b>Description</b> The server encountered an unexpected condition that prevented it from fulfilling the request.</p><p><b>Exception</b></p><pre>javax.servlet.ServletException: org.glassfish.jersey.server.ContainerException: java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/filter/TokenFilter
org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:432)
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:370)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:389)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:342)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:229)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
</pre><p><b>Root Cause</b></p><pre>org.glassfish.jersey.server.ContainerException: java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/filter/TokenFilter
org.glassfish.jersey.servlet.internal.ResponseWriter.rethrow(ResponseWriter.java:278)
org.glassfish.jersey.servlet.internal.ResponseWriter.failure(ResponseWriter.java:260)
org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:460)
org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:285)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:272)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:268)
org.glassfish.jersey.internal.Errors.process(Errors.java:316)
org.glassfish.jersey.internal.Errors.process(Errors.java:298)
org.glassfish.jersey.internal.Errors.process(Errors.java:268)
org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:289)
org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:256)
org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:703)
org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:416)
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:370)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:389)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:342)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:229)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
</pre><p><b>Root Cause</b></p><pre>java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/filter/TokenFilter
com.fasterxml.jackson.databind.ObjectMapper._newReader(ObjectMapper.java:640)
com.fasterxml.jackson.databind.ObjectMapper.reader(ObjectMapper.java:3323)
org.glassfish.jersey.jackson.internal.jackson.jaxrs.base.ProviderBase._configForReading(ProviderBase.java:489)
org.glassfish.jersey.jackson.internal.jackson.jaxrs.base.ProviderBase._endpointForReading(ProviderBase.java:882)
org.glassfish.jersey.jackson.internal.jackson.jaxrs.base.ProviderBase.readFrom(ProviderBase.java:789)
org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.invokeReadFrom(ReaderInterceptorExecutor.java:257)
org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:236)
org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:156)
org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundReadFrom(MappableExceptionWrapperInterceptor.java:73)
org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:156)
org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1091)
org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:874)
org.glassfish.jersey.server.ContainerRequest.readEntity(ContainerRequest.java:271)
org.glassfish.jersey.server.internal.inject.EntityParamValueParamProvider$EntityValueSupplier.apply(EntityParamValueParamProvider.java:97)
org.glassfish.jersey.server.internal.inject.EntityParamValueParamProvider$EntityValueSupplier.apply(EntityParamValueParamProvider.java:80)
org.glassfish.jersey.server.spi.internal.ParamValueFactoryWithSource.apply(ParamValueFactoryWithSource.java:74)
org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:92)
org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:133)
org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:200)
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:103)
org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:493)
org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:415)
org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:104)
org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:277)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:272)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:268)
org.glassfish.jersey.internal.Errors.process(Errors.java:316)
org.glassfish.jersey.internal.Errors.process(Errors.java:298)
org.glassfish.jersey.internal.Errors.process(Errors.java:268)
org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:289)
org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:256)
org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:703)
org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:416)
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:370)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:389)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:342)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:229)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
</pre><p><b>Root Cause</b></p><pre>java.lang.ClassNotFoundException: com.fasterxml.jackson.core.filter.TokenFilter
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1363)
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1186)
com.fasterxml.jackson.databind.ObjectMapper._newReader(ObjectMapper.java:640)
com.fasterxml.jackson.databind.ObjectMapper.reader(ObjectMapper.java:3323)
org.glassfish.jersey.jackson.internal.jackson.jaxrs.base.ProviderBase._configForReading(ProviderBase.java:489)
org.glassfish.jersey.jackson.internal.jackson.jaxrs.base.ProviderBase._endpointForReading(ProviderBase.java:882)
org.glassfish.jersey.jackson.internal.jackson.jaxrs.base.ProviderBase.readFrom(ProviderBase.java:789)
org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.invokeReadFrom(ReaderInterceptorExecutor.java:257)
org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:236)
org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:156)
org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundReadFrom(MappableExceptionWrapperInterceptor.java:73)
org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:156)
org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1091)
org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:874)
org.glassfish.jersey.server.ContainerRequest.readEntity(ContainerRequest.java:271)
org.glassfish.jersey.server.internal.inject.EntityParamValueParamProvider$EntityValueSupplier.apply(EntityParamValueParamProvider.java:97)
org.glassfish.jersey.server.internal.inject.EntityParamValueParamProvider$EntityValueSupplier.apply(EntityParamValueParamProvider.java:80)
org.glassfish.jersey.server.spi.internal.ParamValueFactoryWithSource.apply(ParamValueFactoryWithSource.java:74)
org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:92)
org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:133)
org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:200)
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:103)
org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:493)
org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:415)
org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:104)
org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:277)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:272)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:268)
org.glassfish.jersey.internal.Errors.process(Errors.java:316)
org.glassfish.jersey.internal.Errors.process(Errors.java:298)
org.glassfish.jersey.internal.Errors.process(Errors.java:268)
org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:289)
org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:256)
org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:703)
org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:416)
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:370)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:389)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:342)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:229)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
</pre><p><b>Note</b> The full stack trace of the root cause is available in the server logs.</p><hr class="line" /><h3>Apache Tomcat/9.0.20</h3></body></html>

Related

Rest app (Jersey/JAX-RS) runs in glassfish through eclipse but not when deployed in tomcat

I created a web app using eclipse and (Jersey/JAX-RS). Although when i "run on server" from eclipse in glassfish everything is ok when I deploy the war file I produce either from maven install or from eclipse "export war file" it is deployed succesfully but when i try to access the same rest resources that work in the first option described above, they are not available "404" error.
This is my web.xml file :
<?xml version = "1.0" encoding = "UTF-8"?>
<web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns = "http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id = "WebApp_ID" version = "3.0">
<display-name>Rate it</display-name>
<welcome-file-list>
<welcome-file>login.html</welcome-file>
</welcome-file-list>
<listener>
<listener-class>
com.rateit.util.MyAppServletContextListener
</listener-class>
</listener>
<servlet>
<servlet-name>RateIt login services</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.rateit.login</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>RateIt login services</servlet-name>
<url-pattern>/loginServices/*</url-pattern>
</servlet-mapping>
</web-app>
This is my pom file :
<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.gamechangerapps</groupId>
<artifactId>rateit</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>rateit Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.22.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.eclipsesource.minimal-json/minimal-json -->
<dependency>
<groupId>com.eclipsesource.minimal-json</groupId>
<artifactId>minimal-json</artifactId>
<version>0.9.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.2.2</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>2.19</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.0</version>
</dependency>
</dependencies>
<build>
<finalName>rateit</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webXml>WebContent\WEB-INF\web.xml</webXml>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
and this is my project structure :
project structure
This is LoginServices class
package com.rateit.login;
import java.io.InputStream;
import java.util.List;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.UriBuilder;
import org.apache.log4j.Logger;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import com.rateit.causecodes.LoginCodes;
import com.rateit.inbox.InboxServices;
import com.rateit.mailing.MailServices;
import com.rateit.property.Building;
import com.rateit.property.PropertyDao;
import com.rateit.rating.RatingQueue;
import com.rateit.util.BaseUriProvider;
import com.rateit.util.FileOperations;
import com.rateit.util.GlobalVariables;
import com.rateit.util.JobIdGenerator;
#Path("/Welcome")
public class LoginServices {
UserDao userDao = UserDao.getInstance();
MailServices mailBot = MailServices.getInstance();
FileOperations fileManager = new FileOperations();
PropertyDao propDao = PropertyDao.getInstance();
InboxServices inServ = new InboxServices();
String baseUri = BaseUriProvider.getStreamInstance().getBaseUri();
static Logger logger = Logger.getLogger(LoginServices.class);
#Context
private ServletContext context;
/**
* Service for Login purposes
*
* #FormParam String user email
* #FormParam String user password
*
* #return LoginCodes LOGIN_SUCCESFUL/LOGIN_FAILURE_INVALID_EMAIL/LOGIN_FAILURE_INVALID_PASSWORD/LOGIN_FAILURE_GENERIC
*
*/
#Path("/login")
#POST
#Consumes("application/x-www-form-urlencoded")
public Response login(#FormParam("email") String e, #FormParam("password") String p) {
ResponseBuilder builder = null;
// get new JobId for this operation
int jobId = JobIdGenerator.getStreamInstance().getJobId();
// Create the user object
User userInput = new User(e,p);
String loginCheck = LoginCodes.LOGIN_FAILURE_GENERIC.getDescription();
User userFromDB = userDao.getUser(userInput.getEmail());
logger.info("JobID="+jobId+" for user with email "+userInput.getEmail()+" this user "+userFromDB.getEmail()+" was found in DB");
// login successful
if(userInput.getEmail().equals(userFromDB.getEmail()) && userInput.getPassword().equals(userFromDB.getPassword())){
loginCheck = LoginCodes.LOGIN_SUCCESFUL.getDescription();
builder = Response.seeOther(UriBuilder.fromUri(baseUri+"/login.html").queryParam("user", userFromDB.getEmail()).queryParam("loginCheck", loginCheck).build());
}
// invalid mail
else if(!userInput.getEmail().equals(userFromDB.getEmail())){
loginCheck = LoginCodes.LOGIN_FAILURE_INVALID_EMAIL.getDescription();
builder = Response.seeOther(UriBuilder.fromUri(baseUri+"/login.html").queryParam("loginCheck", loginCheck).build());
}
// invalid password
else if(userInput.getEmail().equals(userFromDB.getEmail()) && !userInput.getPassword().equals(userFromDB.getPassword())){
loginCheck = LoginCodes.LOGIN_FAILURE_INVALID_PASSWORD.getDescription();
builder = Response.seeOther(UriBuilder.fromUri(baseUri+"/login.html").queryParam("loginCheck", loginCheck).build());
}
// both password and mail invalid
else{
builder = Response.seeOther(UriBuilder.fromUri(baseUri+"/login.html").queryParam("loginCheck", loginCheck).build());
}
logger.info("JobID="+jobId+" Login attempt for user "+e+" "+loginCheck);
return builder.build();
}
The problem is the follwing :
The following test can not hit the rest api
#Test
public void loginUserSuccessTest()
{
// Create a user and add him to the DB
User testUser = new User("testuser#rateit.com","1234");
mockDaoObject.addnewUser(testUser);
// Create a HTTP request
Client client = ClientBuilder.newClient();
//WebTarget target = client.target(baseUri+"/loginServices/Welcome/login");
WebTarget target = client.target("http://localhost:8080/rateit/loginServices/Welcome/login");
target.property(ClientProperties.FOLLOW_REDIRECTS, false);
Builder basicRequest = target.request();
// Create a form with the front end parameters
Form form = new Form();
form.param("email", testUser.getEmail());
form.param("password", testUser.getPassword());
// Send the request and get the response
Response response = basicRequest.post(Entity.form(form), Response.class);
// Delete the user
mockDaoObject.deleteUser(testUser);
// Check that the response is success
boolean correctCause = response.getLocation().toString().contains("loginCheck=User+logged+in+successfully");
boolean correctUser = response.getLocation().toString().contains("user=");
assertEquals(true, correctCause);
assertEquals(true, correctUser);
assertEquals(303, response.getStatus());
}
Any advice will be helpful
After some investigation i found the issue. The problem was that some dependencies were missing and also a configuration in eclipse.
I found the error by checking the logs/localhost.date log in tomcat.
There i found the following exception :
15-Oct-2019 23:04:16.492 INFO [http-nio-8080-exec-42] org.apache.catalina.core.ApplicationContext.log Marking servlet [RateIt login services] as unavailable
15-Oct-2019 23:04:16.493 SEVERE [http-nio-8080-exec-42] org.apache.catalina.core.StandardWrapperValve.invoke Allocate exception for servlet [RateIt login services]
java.lang.ClassNotFoundException: org.glassfish.jersey.servlet.ServletContainer
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1365)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1188)
at org.apache.catalina.core.DefaultInstanceManager.loadClass(DefaultInstanceManager.java:540)
at org.apache.catalina.core.DefaultInstanceManager.loadClassMaybePrivileged(DefaultInstanceManager.java:521)
at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:150)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1042)
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:761)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:135)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:678)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1579)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)
Based on this error i fixed the deployment issue with the 3 following steps :
I added the following dependencies in my pom.xml file
org.glassfish.jersey.containers
jersey-container-servlet
2.19
org.glassfish.jersey.core
jersey-server
2.19
I added the maven dependencies in WEB-INF/lib folder through eclipse
MyProject->Properties->Deployment Assembly->Add(Maven Dependencies:source and WEB-INF/lib:Deploy Path
I created the war file through export in eclipse and not through maven task

Apache Camel routing API call to message queue

I have two applications that talk to each other using a REST API.
I would like to know if I can use Apache Camel as a proxy that could "persist" the API calls, for example storing them as messages in ActiveMQ, and then later route the requests to the actual API endpoint.
Practically, I would like to use Apache Camel to "enhance" the API endpoints adding persistence, throttling of requests, etc...
What component do you suggest to use?
You can always try to bridge your HTTP request into a queue, but making the thread wait by forcing the exchangePattern to InOut.
See this example :
import org.apache.activemq.broker.BrokerService;
import org.apache.camel.LoggingLevel;
import org.apache.camel.builder.RouteBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger logger = LoggerFactory.getLogger(SimpleRouteBuilder.class);
public static void main(String[] args) throws Exception {
org.apache.camel.main.Main main = new org.apache.camel.main.Main();
main.addRouteBuilder(new SimpleRouteBuilder());
logger.info("Next call is blocking, ctrl-c to exit\n");
main.run();
}
}
class SimpleRouteBuilder extends RouteBuilder {
private static final Logger logger = LoggerFactory.getLogger(SimpleRouteBuilder.class);
public void configure() throws Exception {
// launching an activemq in background
final BrokerService broker = new BrokerService();
broker.setBrokerName("activemq");
broker.addConnector("tcp://localhost:61616");
Runnable runnable = () -> {
try {
broker.start();
} catch (Exception e) {
e.printStackTrace();
}
};
runnable.run();
// receiving http request but queuing them
from("jetty:http://127.0.0.1:10000/input")
.log(LoggingLevel.INFO, logger, "received request")
.to("activemq:queue:persist?exchangePattern=InOut"); // InOut has to be forced with JMS
// dequeuing and calling backend
from("activemq:queue:persist")
.log(LoggingLevel.INFO, logger,"requesting to destination")
.removeHeaders("CamelHttp*")
.setHeader("Cache-Control",constant("private, max-age=0,no-store"))
.to("jetty:http://perdu.com?httpMethod=GET");
}
}
If you are using maven, here is the pom.xml :
<?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>be.jschoreels.camel</groupId>
<artifactId>camel-simple</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>2.19.2</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jms</artifactId>
<version>2.19.2</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jetty</artifactId>
<version>2.19.2</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-camel</artifactId>
<version>5.15.3</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.15.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.activemq/activemq-kahadb-store -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-kahadb-store</artifactId>
<version>5.15.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
</project>

OSGI : CXF exception with Karaf JAX-RS: No resource methods have been found for resource

I am getting an exception while creating a simple CXF web service with OSGI and Karaf.
Would really appreciate any comments/suggestions for fix.
Here is the description of my project and steps I followed:
Downloaded the Apache Karaf-4.0.7
Run the “mvn clean install” in the command line with the path to my project
Started Karaf console, and run the following commands
feature:repo-add cxf 3.1.8
feature:install cxf/3.1.8
Interface:
public interface MyRestService {
String pingMe(String echo);
}
Implementation:
#Path("/")
public class MyRestServiceImpl implements MyRestService {
#GET
#Path("/{echo}")
#Produces(MediaType.APPLICATION_XML)
public String pingMe(#PathParam("echo") String echo) {
return "Knock Knock: " + echo + " !!";
}
}
OSGI blueprint.xml:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xmlns:cxf="http://cxf.apache.org/blueprint/core" xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs"
xmlns:jaxws="http://cxf.apache.org/blueprint/jaxws"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://www.osgi.org/xmlns/blueprint-ext/v1.1.0 https://svn.apache.org/repos/asf/aries/tags/blueprint-0.3.1/blueprint-core/src/main/resources/org/apache/aries/blueprint/ext/blueprint-ext.xsd
http://cxf.apache.org/blueprint/jaxws http://cxf.apache.org/schemas/blueprint/jaxws.xsd
http://cxf.apache.org/blueprint/jaxrs http://cxf.apache.org/schemas/blueprint/jaxrs.xsd
http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd
http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.1.0.xsd
">
<cxf:bus id=”myBusId”>
<cxf:features>
<cxf:logging></cxf:logging>
</cxf:features>
</cxf:bus>
<jaxrs:server id="myRestService" address="/RestProject/SimpleRestCall">
<jaxrs:serviceBeans>
<ref component-id="myRestImpl" />
</jaxrs:serviceBeans>
</jaxrs:server>
<bean id="myRestImpl" class="com.rest.api.impl.MyRestServiceImpl" />
</blueprint>
Features.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0"
name="restAPI">
<repository>mvn:org.apache.cxf.karaf/apache-cxf/3.1.8/xml/features</repository>
<feature name="test" description="simple test" version="1.0.0-SNAPSHOT">
<details>A Rest server</details>
<!-- CXF and depdendencies -->
<feature version="3.1.8">cxf-jaxrs</feature>
<!-- Jackson and dependencies -->
<bundle>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jsr339-api-2.0/2.6.0</bundle>
<bundle>mvn:com.github.fge/jackson-coreutils/1.8</bundle>
<bundle>mvn:com.fasterxml.jackson.core/jackson-core/2.7.4</bundle>
<bundle>mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-base/2.7.4</bundle>
<bundle>mvn:com.fasterxml.jackson.core/jackson-annotations/2.7.4</bundle>
<bundle>mvn:com.fasterxml.jackson.core/jackson-databind/2.7.4</bundle>
<bundle>mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-json-provider/2.7.4</bundle>
<bundle>mvn:com.github.fge/msg-simple/1.1</bundle>
<bundle>mvn:com.google.guava/guava/16.0.1</bundle>
<bundle>mvn:com.github.fge/btf/1.2</bundle>
<bundle>wrap:mvn:com.google.code.findbugs/jsr305/2.0.1</bundle>
<!-- The myRest Server -->
<bundle>mvn:com.rest.ebb.test/myRest/1.0.0-SNAPSHOT</bundle>
</feature>
</features>
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>
<parent>
<groupId>com.rest.ebb.test</groupId>
<artifactId>myRest-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<groupId>com.rest.ebb.test</groupId>
<artifactId>myRest</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>MyRestServer</name>
<description>A server for test</description>
<url>.example.com</url>
<properties>
<cxf.version>3.1.8</cxf.version>
<skipTests>true</skipTests>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.4.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-Activator>com.ebb.rest.Activator</Bundle-Activator>
<Embed-Dependency>!org.osgi.core,*</Embed-Dependency>
<Embed-Transitive>true</Embed-Transitive>
<Import-Package>
!com.google.protobuf,!com.google.protobuf.*,
!com.jcraft.*,
!com.ning.*,
!groovy.lang,
!javassist,
!lzma.*,
!net.jpountz.*,
!org.apache.*,
!org.bouncycastle.*,
!org.codehaus.*,
!org.eclipse.*,
!org.jboss.*,
!rx,
!sun.security.*,
!net.bytebuddy.*,
!org.HdrHistogram,
!org.slf4j.event,
!org.xerial.*,
!sun.reflect,
!sun.misc,
!sun.util.calendar,
!com.sun.jdi.*,
!jersey.repackaged.com.google.common.*,
!javax.servlet,
*
</Import-Package>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.24</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
<version>2.24</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
<type>bundle</type>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-multibindings</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-core</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.threeten</groupId>
<artifactId>threetenbp</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>3.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>${cxf.version}</version>
</dependency>
</dependencies>
</project>
Errors:
Am not able to deploy osgi bundles in Karaf, and getting the following errors:
2017-01-06 11:00:39,340 | WARN | pool-9-thread-1 | ResourceUtils | 141 - org.apache.cxf.cxf-rt-frontend-jaxrs - 3.1.8 | No resource methods have been found for reso
class com.rest.api.impl.MyRestServiceImpl
2017-01-06 11:00:39,373 | ERROR | pool-9-thread-1 | AbstractJAXRSFactoryBean | 141 - org.apache.cxf.cxf-rt-frontend-jaxrs - 3.1.8 | No resource classes found
2017-01-06 11:00:39,375 | WARN | pool-9-thread-1 | BeanRecipe | 33 - org.apache.aries.blueprint.core - 1.6.2 | Object to be destroyed is not an instance of Unwra
edBeanHolder, type: null
2017-01-06 11:00:39,385 | ERROR | pool-9-thread-1 | BlueprintContainerImpl | 33 - org.apache.aries.blueprint.core - 1.6.2 | Unable to start blueprint container for bundle mvn:com.abb.ecc.my/myRest/1.0.0-SNAPSHOT
org.osgi.service.blueprint.container.ComponentDefinitionException: Unable to initialize bean myRestService
at org.apache.aries.blueprint.container.BeanRecipe.runBeanProcInit(BeanRecipe.java:738)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BeanRecipe.internalCreate2(BeanRecipe.java:848)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BeanRecipe.internalCreate(BeanRecipe.java:811)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.di.AbstractRecipe$1.call(AbstractRecipe.java:79)[33:org.apache.aries.blueprint.core:1.6.2]
at java.util.concurrent.FutureTask.run(FutureTask.java:266)[:1.8.0_51]
at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:88)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BlueprintRepository.createInstances(BlueprintRepository.java:255)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BlueprintRepository.createAll(BlueprintRepository.java:186)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BlueprintContainerImpl.instantiateEagerComponents(BlueprintContainerImpl.java:724)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BlueprintContainerImpl.doRun(BlueprintContainerImpl.java:411)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BlueprintContainerImpl.run(BlueprintContainerImpl.java:276)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:300)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:269)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:265)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BlueprintExtender.modifiedBundle(BlueprintExtender.java:255)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.customizerModified(BundleHookBundleTracker.java:500)[43:org.apache.aries.util:1.1.1]
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.customizerModified(BundleHookBundleTracker.java:433)[43:org.apache.aries.util:1.1.1]
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$AbstractTracked.track(BundleHookBundleTracker.java:725)[43:org.apache.aries.util:1.1.1]
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.bundleChanged(BundleHookBundleTracker.java:463)[43:org.apache.aries.util:1.1.1]
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$BundleEventHook.event(BundleHookBundleTracker.java:422)[43:org.apache.aries.util:1.1.1]
at org.apache.felix.framework.util.SecureAction.invokeBundleEventHook(SecureAction.java:1179)[org.apache.felix.framework-5.4.0.jar:]
at org.apache.felix.framework.util.EventDispatcher.createWhitelistFromHooks(EventDispatcher.java:731)[org.apache.felix.framework-5.4.0.jar:]
at org.apache.felix.framework.util.EventDispatcher.fireBundleEvent(EventDispatcher.java:486)[org.apache.felix.framework-5.4.0.jar:]
at org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:4541)[org.apache.felix.framework-5.4.0.jar:]
at org.apache.felix.framework.Felix.startBundle(Felix.java:2172)[org.apache.felix.framework-5.4.0.jar:]
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:998)[org.apache.felix.framework-5.4.0.jar:]
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:984)[org.apache.felix.framework-5.4.0.jar:]
at org.apache.karaf.features.internal.service.FeaturesServiceImpl.startBundle(FeaturesServiceImpl.java:1286)[10:org.apache.karaf.features.core:4.0.7]
at org.apache.karaf.features.internal.service.Deployer.deploy(Deployer.java:846)[10:org.apache.karaf.features.core:4.0.7]
at org.apache.karaf.features.internal.service.FeaturesServiceImpl.doProvision(FeaturesServiceImpl.java:1176)[10:org.apache.karaf.features.core:4.0.7]
at org.apache.karaf.features.internal.service.FeaturesServiceImpl$1.call(FeaturesServiceImpl.java:1074)[10:org.apache.karaf.features.core:4.0.7]
at java.util.concurrent.FutureTask.run(FutureTask.java:266)[:1.8.0_51]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)[:1.8.0_51]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)[:1.8.0_51]
at java.lang.Thread.run(Thread.java:745)[:1.8.0_51]
Caused by: org.apache.cxf.service.factory.ServiceConstructionException
at org.apache.cxf.jaxrs.JAXRSServerFactoryBean.create(JAXRSServerFactoryBean.java:219)
at org.apache.cxf.jaxrs.JAXRSServerFactoryBean.init(JAXRSServerFactoryBean.java:142)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)[:1.8.0_51]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)[:1.8.0_51]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)[:1.8.0_51]
at java.lang.reflect.Method.invoke(Method.java:497)[:1.8.0_51]
at org.apache.aries.blueprint.utils.ReflectionUtils.invoke(ReflectionUtils.java:299)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BeanRecipe.invoke(BeanRecipe.java:980)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BeanRecipe.runBeanProcInit(BeanRecipe.java:736)[33:org.apache.aries.blueprint.core:1.6.2]
... 34 more
Caused by: org.apache.cxf.service.factory.ServiceConstructionException: No resource classes found
at org.apache.cxf.jaxrs.AbstractJAXRSFactoryBean.checkResources(AbstractJAXRSFactoryBean.java:317)
at org.apache.cxf.jaxrs.JAXRSServerFactoryBean.create(JAXRSServerFactoryBean.java:159)
... 42 more
Try to put the jax-rs annotations on the service interface.
Another possible cause is that the annotation package is not imported. You block a lot of imports in your pom. Can you check without these definitions.
On my side your code works but I had to change the following things:
Remove the cxf:bus from the blueprint
Remove the #Path on the implementation class
Change the import section in the pom.xml
Implementation:
package com.mycompany.testcxf;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
public class MyRestServiceImpl implements MyRestService {
#Override
#GET
#Path("/{echo}")
#Produces(MediaType.APPLICATION_XML)
public String pingMe(#PathParam("echo") String echo) {
return "Knock Knock: " + echo + " !!";
}
}
pom.xml:
<osgi.export.package>{local-packages}</osgi.export.package>
<osgi.import.package>
com.mycompany.testcxf*,
*
</osgi.import.package>
and I only import the dependency:
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>2.7.13</version>
</dependency>
Note I cannot test the CXF version 3 as you because my OSGI container is bound to this version. However this setup works perfectly for me, then it could be an issue with the CXF version and some incompatibilities with the embedded http server (Jetty?).
My setup is ServiceMix 5.1.4 with:
Version 2.3.9 of Apache Karaf
Version 2.13.3 of Camel
Version 2.7.13 of CXF

404 Error in Postman - Spring Rest

I am getting a 404 error when I test my REST Spring WebService in Postman.
Can anyone suggest a solution??
My code :
src/main/resources/spring/application-config.xml
-------------------------------------------------------------------------------------------------------------------------------------------
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="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">
<!-- Uncomment and add your base-package here:
<context:component-scan
base-package="org.springframework.samples.service"/> -->
</beans>
-------------------------------------------------------------------------------------------------------------------------------------------
src/main/resources/logback.xml
-------------------------------------------------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<!-- configuration file for LogBack (slf4J implementation)
See here for more details: http://gordondickens.com/wordpress/2013/03/27/sawing-through-the-java-loggers/ -->
<configuration scan="true" scanPeriod="30 seconds">
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
<!-- To enable JMX Management -->
<jmxConfigurator/>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%-5level %logger{0} - %msg%n</pattern>
</encoder>
</appender>
<!--<logger name="org.hibernate" level="debug"/> -->
<!-- Uncomment and add your logger here:
<logger name="org.springframework.samples.service.service" level="debug"/> -->
<root level="info">
<appender-ref ref="console"/>
</root>
</configuration>
---------------------------------------------------------------------------------------------------------------------------------------------
src/main/webapp/WEB-INF/mvc-config.xml
---------------------------------------------------------------------------------------------------------------------------------------------
<?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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.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">
<!-- Uncomment and your base-package here:
<context:component-scan
base-package="org.springframework.samples.web"/> -->
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- Example: a logical view name of 'showMessage' is mapped to '/WEB-INF/jsp/showMessage.jsp' -->
<property name="prefix" value="/WEB-INF/view/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
---------------------------------------------------------------------------------------------------------------------------------------------
src/main/webapp/WEB-INF/web.xml
---------------------------------------------------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>ManageUserRoles</display-name>
<!--
- Location of the XML file that defines the root application context.
- Applied by ContextLoaderListener.
-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/application-config.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--
- Servlet that dispatches request to registered handlers (Controller implementations).
-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
//////////////////////////Controller///////////////////////////////
package com.controller;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.model.Role;
#Controller
public class RoleController {
private static final Logger logger = LoggerFactory.getLogger(RoleController.class);
Map<String, Role> roleData = new HashMap<String, Role>();
#RequestMapping(value = "/role/{role_name}", method = RequestMethod.GET,headers="Accept=application/json")
public #ResponseBody Role findRole(#PathVariable("role_name") String role_name)
{
logger.info("Get a single role with name="+role_name);
return roleData.get(role_name);
}
#RequestMapping(value = "/roles", method = RequestMethod.GET)
public #ResponseBody List<Role> getAllRoles()
{
logger.info("Start getAllRoles.");
List<Role> list_roles = new ArrayList<Role>();
list_roles = createRoleList();
return list_roles;
}
public List<Role> createRoleList()
{
Role role1 = new Role("NP Sherm Test", "NP Test", "Active");
Role role2 = new Role("Sherm Employee Test", "Employee access test role", "Active");
Role role3 = new Role("Sherm Manager Test", "Manager test user role", "Active");
List<Role> list_roles = new ArrayList<Role>();
list_roles.add(role1);
list_roles.add(role2);
list_roles.add(role3);
return list_roles;
}
#RequestMapping(value="/roles/new/",method=RequestMethod.POST,headers="Accept=application/json")
public #ResponseBody Role addRole(#RequestBody Role role)
{
logger.info("Start Add Role");
Role roleGet = roleData.put(role.getRole_name(), role);
return roleGet;
}
#RequestMapping(value="/roles/new/",method=RequestMethod.PUT,headers="Accept=application/json")
public #ResponseBody Role editRole(#RequestBody Role role)
{
Role role_update = new Role();
role.setRole_name(role.getRole_name());
role.setRole_desc(role.getRole_desc());
role.setRole_status(role.getRole_status());
return role_update;
}
}
/////////////////////////////////////Model///////////////////////////////
package com.model;
public class Role {
private String role_name;
private String role_desc;
private String role_status;
public Role(){}
public Role(String role_name, String role_desc, String role_status) {
super();
this.role_name = role_name;
this.role_desc = role_desc;
this.role_status = role_status;
}
public String getRole_name() {
return role_name;
}
public void setRole_name(String role_name) {
this.role_name = role_name;
}
public String getRole_desc() {
return role_desc;
}
public void setRole_desc(String role_desc) {
this.role_desc = role_desc;
}
public String getRole_status() {
return role_status;
}
public void setRole_status(String role_status) {
this.role_status = role_status;
}
}
//////////////////////////////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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.samples.service.service</groupId>
<artifactId>ManageUserRoles</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<!-- Generic properties -->
<java.version>1.6</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- Web -->
<jsp.version>2.2</jsp.version>
<jstl.version>1.2</jstl.version>
<servlet.version>2.5</servlet.version>
<!-- Spring -->
<spring-framework.version>3.2.3.RELEASE</spring-framework.version>
<!-- Hibernate / JPA -->
<hibernate.version>4.2.1.Final</hibernate.version>
<!-- Logging -->
<logback.version>1.0.13</logback.version>
<slf4j.version>1.7.5</slf4j.version>
<!-- Test -->
<junit.version>4.11</junit.version>
</properties>
<dependencies>
<!-- Spring MVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Other Web dependencies -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${servlet.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>${jsp.version}</version>
<scope>provided</scope>
</dependency>
<!-- Spring and Transactions -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Logging with SLF4J & LogBack -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>runtime</scope>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!-- Test Artifacts -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring-framework.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
As you don't have any specific application context, the problem is with the current URL mapping i.e., the URI ManageUserRoles did not map to the controller, so change the code as below:
#Controller("ManageUserRoles")
public class RoleController {
// Add all you existing handler methods
}
After your UPDATE 1:
Also, your componentscan is not correct in mvc-config.xml because of which controller can't be detected:
base-package="org.springframework.samples.web" change it to base-package="com.controller"

spring mvc rest protocol buffers http 406 not acceptable error

I am using Spring MVC 4.1.5 with its REST support trying to get a web service working with google protocol buffers message format. I have seen a lot of posts that are mentioning this issue with JSON format but none with google protocol buffers format.
Also I don't see Spring framework docs have a MediaType for protobufs (more on that below) My code is posted here on github
Here's my controller code (using or not using produces="application-xprotobuf" makes no difference - same 406 not acceptable error)
#RestController
#RequestMapping("/ws")
#EnableWebMvc
public class CustomerRestController {
#Autowired
private CustomerRepository customerRepository;
//#RequestMapping(value="/customers/{id}", method = RequestMethod.GET, produces="application/x-protobuf")
#RequestMapping(value="/customers/{id}", method = RequestMethod.GET)
public CustomerProtos.Customer customer(#PathVariable Integer id) {
return this.customerRepository.findById(id);
}
#Bean
ProtobufHttpMessageConverter protobufHttpMessageConverter() {
return new ProtobufHttpMessageConverter();
}
private CustomerProtos.Customer customer(int id, String f, String l, Collection<String> emails) {
String emailAddressString = "defaultEmail#address.com";
for (String email : emails) {
emailAddressString = email;
break;
}
EmailAddress emailAddress = CustomerProtos.Customer.EmailAddress.newBuilder()
.setType(CustomerProtos.Customer.EmailType.PROFESSIONAL).setEmail(emailAddressString).build();
return CustomerProtos.Customer.newBuilder().setFirstName(f).setLastName(l).setId(id).addEmail(emailAddress)
// .addAllEmail(emailAddresses)
.build();
}
#Bean
CustomerRepository customerRepository() {
return new CustomerRepositoryImpl();
}
}
here's my web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>demo</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/rest-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
Here's my pom.xml, please note that i do have google protobuf libaries added here and they do end up in WEB-INF/lib folder of the deployed .war file.
<?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>org.test</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.0.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>demo.DemoApplication</start-class>
<java.version>1.8</java.version>
<jackson.version>2.5.3</jackson.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>com.googlecode.protobuf-java-format</groupId>
<artifactId>protobuf-java-format</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-legacy</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Here's my test client
package demo;
import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.client.RestTemplate;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class DemoApplicationTests {
#Configuration
public static class RestClientConfiguration {
#Bean
RestTemplate restTemplate(ProtobufHttpMessageConverter hmc) {
return new RestTemplate(Arrays.asList(hmc));
}
#Bean
ProtobufHttpMessageConverter protobufHttpMessageConverter() {
return new ProtobufHttpMessageConverter();
}
}
#Autowired
private RestTemplate restTemplate;
#Test
public void contextLoaded() {
ResponseEntity<CustomerProtos.Customer> customer = restTemplate.getForEntity(
"http://localhost:7001/demo-0.0.1-SNAPSHOT/ws/customers/2", CustomerProtos.Customer.class);
System.out.println("customer retrieved: " + customer.toString());
}
}
When I run the client from command line using mvn test
I get the following error
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.697 sec <<< FAILURE! - in demo.DemoApplicationTests
contextLoaded(demo.DemoApplicationTests) Time elapsed: 0.037 sec <<< ERROR!
org.springframework.web.client.HttpClientErrorException: 406 Not Acceptable
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:641)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:597)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:557)
at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:289)
at demo.DemoApplicationTests.contextLoaded(DemoApplicationTests.java:42)
I saw people suggesting using a contentNegotiationManager
In my rest-servlet.xml I have mvc:annotation-driven tag
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<context:component-scan base-package="demo" />
<mvc:annotation-driven />
</beans>
Also I have dropped in a webConfig.java in demo package
package demo;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
/**
* Total customization - see below for explanation.
*/
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false).
favorParameter(true).
parameterName("mediaType").
ignoreAcceptHeader(true).
useJaf(false).
defaultContentType(MediaType.TEXT_PLAIN).
mediaType("xml", MediaType.APPLICATION_XML).
mediaType("json", MediaType.APPLICATION_JSON).
mediaType("x-protobuf", MediaType.ALL)
;
}
}
I get the 406 not acceptable error with and without the webconfig.java (which is doing the work of contentNegotationManager).
I haven't been able to find a MediaType.APPLICATION_XPROTOBUF in Spring 4.1.3 or even 4.2.3 jars .
So I have left that value to MediaType.ALL ( I think that should work ?)
When I run the test client I get this message before actually running the test..
09:27:26.198 [main] DEBUG o.s.web.client.RestTemplate - Created GET request for "http://localhost:7001/demo-0.0.1-SNAPSHOT/ws/customers/2"
09:27:26.199 [main] DEBUG o.s.web.client.RestTemplate - Setting request Accept header to [application/x-protobuf, text/plain, application/xml, application/json]
09:27:26.245 [main] DEBUG o.s.web.client.RestTemplate - GET request for "http://localhost:7001/demo-0.0.1-SNAPSHOT/ws/customers/2" resulted in 406 (Not Acceptable); invoking error
handler
It clearly shows its setting the accept headers to include "application-xprotobuf" value as well.
Not sure what I am missing in this case.
I had the same issue with the controller failing with 406: Not Acceptable. After a lot of tracing I figured out the statement in the example:
Spring Boot automatically registers HttpMessageConverter beans so we need only define the ProtobufHttpMessageConverter bean and it gets configured appropriately.
is to be understood literally, since without Spring Boot no converter registration happens. The bean is instantiated, but it's never registered in the list of HttpMessageConverters.
I've solved it by explicitly registering a ProtobufHttpMessageConverter instance:
#Configuration
#EnableWebMvc
#ComponentScan
public class AppConfig extends WebMvcConfigurerAdapter {
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new ProtobufHttpMessageConverter());
super.configureMessageConverters(converters);
}
}
You don't need to declare a separate bean for it (unless you plan to call it explicitly).
Also note that overriding configureMessageConverters() disables all standard converters; if you mean to extend the list of stock converters rather than replace it, override extendMessageConverters() instead.