RestEasy Jax-RS in Jboss 7.1 doesn't work - rest

I'm trying to deploy a simple web application under JBoss AS 7.1 which comes bundled with resteasy. According to the documentation all that is needed is (at bare minimum) is an empty web.xml, a class with annotated #ApplicationPath("/mypath") and #Path("/other_stuff") for your other classes
The documentation I'm following is here:
https://docs.jboss.org/author/display/AS7/JAX-RS+Reference+Guide
https://docs.jboss.org/author/display/AS7/Java+API+for+RESTful+Web+Services+(JAX-RS)
Still, when I hit:
host:8080/warname/applicationpath/path
I receive a 404 error on the webpage but nothing in the logs.
Is there a configuration file I need to change in order for JAX-RS to work?
Thank you in advance for any help!

Empty web.xml will do.
Just add some resteasy dependency to your classpath. For instance, if you use maven you can add this to your pom.xml:
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>2.3.1.GA</version>
<scope>provided</scope> <!-- provided if youre deploying to jboss as 7.1 -->
</dependency>
Then set up the application using only this class:
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("/rest")
public class JaxRsActivator extends Application {
}
Just to make sure, add a resource like this:
#Path("/hello")
public class HelloResource {
#GET
#Produces("text/plain")
public String helloResource() {
return "Hello! It's "+new Date();
}
}
And that's all you need. Deploy it at a JBoss AS 7.1 and get to it, say:
http://127.0.0.1:8080/mywarname/rest/hello
Edit:
I have created a java war maven project with the bare minimum strucutre:
-pom.xml
-src
|
--main
|
--java
|
--rest
|
--HelloResource.java
--JaxRsActivator.java
I called it simpleRest as seen below. All the archives are exactly as shown:
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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>simpleRest</groupId>
<artifactId>simpleRest</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>2.3.1.GA</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<!-- So maven doesn't require web.xml -->
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
HelloResource.java
package rest;
import java.util.Date;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
#Path("/hello")
public class HelloResource {
#GET
#Produces("text/plain")
public String helloResource() {
return "Hello! It's "+new Date();
}
}
JaxRsActivator.java:
package rest;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("/rest")
public class JaxRsActivator extends Application {
}
This generates a simpleRest.war (through mvn clean package). I then deploy it to a freshly installed JBoss AS 7.1.1.Final. As you can see, no reference is made to JAX-RS in the log during the deploy:
22:48:08,677 INFO [org.jboss.as.server.deployment] (MSC service thread 1-1) JBAS015876: Starting deployment of "simpleRest.war"
22:48:09,318 INFO [org.jboss.web] (MSC service thread 1-4) JBAS018210: Registering web context: /simpleRest
22:48:09,492 INFO [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS018559: Deployed "simpleRest.war"
After that, the URL is available as expected:
http://127.0.0.1:8080/simpleRest/rest/hello
Notice that everything else gives a 404 error. But it is a different kind of 404.
http://127.0.0.1:8080/simpleRest/ gives:
HTTP Status 404 - /simpleRest/
That is a page not found error. On the other hand, http://127.0.0.1:8080/simpleRest/rest gives:
HTTP Status 404 - Could not find resource for relative : / of full path: http://127.0.0.1:8080/simpleRest/rest
That is a resource (REST service) not found error. This way you know JAX-RS is acting, though it did not have a handler for that path.

Take a look at jboss quickstarts: http://www.jboss.org/jdf/quickstarts/jboss-as-quickstart/
You can get them from http://www.jboss.org/jbossas/downloads
These are working out of box. For helloword-rs quickstart I can see web.xml with content:
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
and also comment:
One of the way of activating REST Servises is adding these lines, the server is responsible for adding the corresponding servlet automatically. If the src folder, org.jboss.as.quickstarts.rshelloworld.HelloWorld class has the Annotations to receive REST invocation.

If you are using JBoss AS 7.1, you also need to add the "resteasy.resources" context parameter. You also need to send the init-param to the HttpServletDispatcher servlet.
I found the solution at the following link : http://www.javaroots.com/2013/05/creating-rest-services-with-rest-easy.html
Just one typo error(maybe!!) in the above link. In the "RootRestService" change the method signature of the getClasses() method to public Set<Class<?>> getClasses().
Thats it! It solved my 3 day headache. Hope it helps you too!! :)

Even though acdcjunior's answer is great and very thorough, i'd like to reinfoce Andrzej's answer.
It works as a charm and it is by far the more straightforward one. The JBoss quickstart samples (also available on GitHub) are always a great resource to answer questions like this one.

Related

open api swagger-ui giving white label error page (404) after moving the project as a module in a project

I have the working project in Spring boot which was a standalone app. Now, to modularize, I have split the app and put the api in a module. Earlier the swagger-ui.html page was working, but after this, it is not working.
my pom.xml has these 2 dependencies
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.5.1</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-data-rest</artifactId>
<version>1.5.1</version>
</dependency>
My Application.java has the following code
#Bean
#Profile("!prod")
public OpenAPI caffeAPIRegistry() {
return new OpenAPI()
.info(new Info().title("My Awesome API")
.description("Powering UI")
.version("v3.0.0")
.license(new License().name("google Inc.,").url("https://google.com")));
}
The pom.xml fragment for the parent project mapping
<parent>
<artifactId>API_Project</artifactId>
<groupId>com.abc</groupId>
<version>2.0.0.RELEASE</version>
</parent>
I have been searching for a long time in internet if moving api as a module might require any other change, but could not find any help.
Are the interfaces with the REST annotations in a different package? if yes then that is the issue.

Rest Easy Hello world example showing 404 not found error

As I didn't found any good tutorial for RestEasy + WildFly, I'm following this (https://robferguson.org/blog/2016/12/02/getting-started-with-resteasy/) tutorial and created a simple Hello World example of JAX-RS project using Resteasy 3.7.0.Final + Wildfly 13 + Java 8 + maven. This tutorial is actually using Jetty Http server.
Here is the Resource class :
#Path("/hello")
#Produces(MediaType.TEXT_PLAIN)
public class MessageResource {
#GET
#Path("/{param}")
public Response printMessage(#PathParam("param") String msg) {
String result = "Hello " + msg + "!";
return Response.status(200).entity(result).build();
}
}
And a class extending javax.ws.rs.core.Application - (all Rest resources will be registered by this class automatically)
#ApplicationPath("")
public class HelloWorldApplication extends Application {
public HelloWorldApplication() {}
#Override
public Set<Object> getSingletons() {
HashSet<Object> set = new HashSet<Object>();
set.add(new MessageResource());
return set;
}
}
In addition I have added jboss-deployment-structure.xml (which is not part of the tutorial) under WEB-INF to exclude the following modules :
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<exclude-subsystems>
<subsystem name="resteasy" />
</exclude-subsystems>
<exclusions>
<module name="javaee.api" />
<module name="javax.ws.rs.api"/>
<module name="org.jboss.resteasy.resteasy-jaxrs" />
</exclusions>
<local-last value="true" />
</deployment>
</jboss-deployment-structure>
I suppose this excludes resteasy modules bundled with Wildfly (please correct me if I'm wrong), since I'm using latest version of RestEasy in pom.xml :
<properties>
<resteasy.version>3.7.0.Final</resteasy.version>
</properties>
In maven configuration I have removed the jetty plugin, and rest of the part in pom.xml is same as in tutorial example here, except the RestEasy version.
https://github.com/Robinyo/resteasy/blob/master/examples/helloworld/pom.xml
But when I try to run the example with URL http://localhost:8080/hello/World, I'm getting 404 - Not Found error.
Is there any part missing in maven configuration or wildfly configuration?

REST with JAX-RS tomcat server returning "requested resource is not available"

I was following short tutorial on creating REST api using JAX-RS. I am using Tomcat server v7.0. When I run the application on the server I get error 404-requested resource is not available.
The project is Maven based, and my pom.xml file includes the following line
<properties>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
I do not have web.xml file as a result. That was how the tutorial was achieved. I do not have index.html/jsp file. I have created two classes RESTconfig.java and BookResources.java
...import statements
#ApplicationPath("api")
public class RESTconfig extends Application {
}
...import statements
#Path("books")
public class BookResources {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String books() {
return "Hello world";
}
}
My pom.xml file looks like this
<groupId>com.dere</groupId>
<artifactId>myrest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
Once I run the application on the server and go to http://localhost:9090 I am able to see Tomcat home page, but if try to get data http://localhost:9090/myrest/api/books I get the 404 error, i.e requested resource is not available, I mentioned above.
Most of the examples or usage I saw online involve using web.xml and providing root of the application and using a servlet. This is my first exposure to building REST api. I may have misunderstood the whole thing or I skipped some step. I look forward for your help.
I am using Eclipse Photon for Java EE
Look at this
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
This is nothing more than basically a bunch of interfaces for the EE spec. There is no implementation. Java EE servers will have the implementation. Tomcat is not an EE server. The only part of the EE spec it will definitely have the implementation for is Servlets and JSP (the web profile). If you want an EE server, checkout Glassfish or Wildfly.
You are trying to work with the JAX-RS spec, where Tomcat for sure by default does not have an implementation for. So you need to add that implementation. The easiest implementation, IMO to get started with, is Jersey. You can simply add this dependency
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.25.1</version>
</dependency>
and it will get you up and running. Keep the Jersey User Guide handy. It will come in use.

Maven Exec plugin, ClassLoader ClassNotFoundException

I've tried many suggestions on StackOverflow, and tested with many combinations of setup and pom.xml for 3 days, none of them works. Please help.
I started with a big project with a lot of dependencies, spring-boot, hibernate, etc. Then I create another small console project which import and use some classes from the big project. They are not parent and child project. All I do is add <dependency/> to the child project pom, like this.
P.S. the big project has a <parent/> spring-boot-starter-parent and use spring-boot-maven-plugin.
<dependency>
<groupId>myGroup</groupId>
<artifactId>bigProject</artifactId>
<version>1.0.1</version>
</dependency>
This works on Eclipse with m2e, I just use "Run as" java application and the small project works.
But I need to upload and run those project on my linux VM, which does not use GUI and Eclipse, only terminal.
Then after some reading, I try to use maven exec plugin to run the small project. My steps:
1. do mvn clean install on the big project, confirmed that it appears in my /.m2, local repository.
2. run mvn compile on small project
3. run mvn exec:java on small project
It fails on step 2, those import ... in the class of small project throw package xxx does not exist. maven fail with compilation error.
Then, I try to simplify the problem. I create two test projects with only 1 class, myLib and HelloWorld console application, then I add myLib dependency (pom). HelloWorld project to print a message from the class in myLib package. run step 1 to 3. It works.
public class App
{
public static void main( String[] args )
{
//SystemLog from big project, does not work
//SystemLog log = new SystemLog();
//log.setValue("test value");
//System.out.println(log.getValue());
//CustomMessage from myLib, works fine
CustomMessage cm = new CustomMessage();
cm.setTheMessage("custom message");
System.out.println(cm.getTheMessage() );
System.out.println(CustomMessage.defaultMsg);
}
}
pom.xml of small project
<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>test</groupId>
<artifactId>dependOnOthers</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>dependOnOthers</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>myLibrary</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com</groupId>
<artifactId>bigproject</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.5.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<includePluginDependencies>true</includePluginDependencies>
<mainClass>test.dependOnOthers.App</mainClass>
<!-- <arguments> <argument>argument1</argument> </arguments> -->
<!-- <arguments> <argument>-classpath</argument> <argument>target/lib/bigproject-1.0.1.jar</argument>
</arguments> -->
</configuration>
</plugin>
</plugins>
</build>
</project>
Then I add a reference to big project, try to print a log message using HelloWorld, it pass step 2, mvn compile, but when I do step 3, mvn exec:java, java.lang.ClassLoader.loadClass() throw ClassNotFoundException on the line where I new an SystemLog() instance, the class defined in big project.
Summarize:
Goal: try to run a console application using Maven exec plugin, which has a dependency on another project, that is installed in local repo /.m2
The SystemLog class is a model class with hibernate annotations.
1. small project depend on big project, fail on mvn compile, package does not exist.
2. HelloWorld depend on myLib, works fine.
3. HelloWorld depend on big project, fail at runtime with ClassNotFoundException.
It's a little late but i ran in the same error, migrating a project from 1.5.3 to 2.1.4
I have found a solution for this problem.
Spring Boot has changed the jar structure in version 2.0.0+, so you don't need to specify your class as <mainClass>test.dependOnOthers.App</mainClass>, you need to point JarLauncher as main entry point.
When the plugin will execute the jar, java will call the main method JarLauncher and several code of spring will be called after that he reads the manifest and call the class definied in Start-Class:. in your case test.dependOnOthers.App.
<configuration>
<!-- Since version 2 of spring, the jar is packed in
another way and has his main method here, don't worry in the MANIFEST file is described which file to boot -->
<mainClass>org.springframework.boot.loader.JarLauncher</mainClass>
The old strucutre of Spring 1.0, was the classical java way todo it, so the java classloader can load it without problems and refer to the class when it is in the classpath, with the version 2.0.0+, they copy user class files and dependency into BOOT-INF, so the java classloader cannot load it anymore, you need to use the Spring classloader to get the class instance.
I have a workaround and know what is causing the problem, but don't know all the details, hope that someone will comment on this, or elaborate the answer.
The thing that cause this problem is spring-boot-maven-plugin, which I use to run spring-boot embedded tomcat server, using mvn spring-boot:run. This plugin seems to change something on the .jar file, maybe the manifest?
The workaround is to remove this plugin, run mvn clean install, that .jar installed in local repository will work correctly. run mvn compile on the small project. Then add the plugin back to big project, run mvn spring-boot:run
I do not know what the plugin changes that result in a .jar with package not exist, does it changes package name?
My workaround is clumsy, if there is a way to choose to compile with or without spring-boot-maven-plugin by defining maven goal, so that I do not need to change the pom for different build (with/without plugin). That would be a better solution.

Using default Providers/MessageBodyWriters in Jersey 2

Just starting with Jersey, I've been trying to reproduce the simple example in the latest Jersey documentation 'building responses'. This part, as far as I understand, should show how Response and ResponseBuilder can be used to easily return a response in combination with Entity<T> for response content.
Now, the documentation states that several data types are by default supported (here: 'Representations and Java types'). String prime among them, matching any media type.
Of all the variations I've tried, the following is the simplest:
#POST
public Response post() {
URI createdUri;
try {
createdUri = new URI("http://test.lan");
} catch (final URISyntaxException e) {
throw new WebApplicationException(e);
}
return Response.created(createdUri).entity(Entity.text("someContent")).build();
}
I've always gotten the same error (full stacktrace below) on calling the request:
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=text/plain, type=class javax.ws.rs.client.Entity, genericType=class javax.ws.rs.client.Entity.
I believe it's saying that a suitable provider wasn't found for this Entity generic-type. However, String should be supported OOTB?
I found that StringMessageProvider is probably the Jersey 1 implementation of this provider, and the closest related classes I found in my Jersey 2 libraries arer the classes in org.glassfish.jersey.message.internal in jersey-common. Among the many providers there is the StringMessageProvider, which appears to me like a potential intended provider for this.
I've looked up the issue, and while there's plenty of people who get this when incorrectly trying to use a custom Provider, I found nothing about the default OOTB providers not working..
I've checked my libs, and right now I have the following dependencies in my pom (among others):
jersey-container-servlet-core
jersey-client
jersey-common
jersey-server
I've looked online but this seems to be all I need, although I have not with certainty found the right provider classes for String and JAXB/JSON in the jars.
Context
Maven project
with tomcat servlet-api 6.0.29
Version 2.6 of all mentioned jersey libs
Eclipse kepler
Using tomcat6 maven plugin to run embedded tomcat (works fine so far)
Fiddler request used to test
POST HTTP/1.1
User-Agent: Fiddler
Host: 127.0.0.1
Content-Length: 0
And again tried several variations.
Full stacktrace
06-Jan-2015 21:13:54 org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor aroundWriteTo
SEVERE: MessageBodyWriter not found for media type=text/plain, type=class javax.ws.rs.client.Entity, genericType=class javax.ws.rs.client.Entity.
06-Jan-2015 21:13:54 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet TestService threw exception
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=text/plain, type=class javax.ws.rs.client.Entity, genericType=class javax.ws.rs.client.Entity.
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:247)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo(JsonWithPaddingInterceptor.java:103)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:88)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1154)
at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:571)
at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:378)
at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:368)
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:262)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:319)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:236)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1028)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:373)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:381)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:344)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:219)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:662)
EDIT
The same error (for application/json) ocurs now that I've annotated a class with #XmlRootElement and try to return it in a method per the Jersey docs:
#GET
#Produces(MediaType.APPLICATION_JSON)
public Foo sampleFoo() {
Foo foo = new Foo();
return foo;
}
Where Foo is annotated with #XmlRootElement.
I also added jersey-media-json-jackson as dependency, which I can see contains an explicit JSONJaxb provider. However, it doesn't seem to be picked up somehow.
First Issue:
javax.ws.rs.client.Entity is a client side class. The JAX-RS spec doesn't say anything about its usage on the server side. But I can confirm with many different tests, that the result will be similar to what you are seeing (with Jersey at least). With Resteasy, it will just send out the Entity.toString()
Since this doesn't work for either Resteasy or Jersey, I won't say it's a bug, but possible a mistake in the Jersey documentation, which exampled it usage as follows:
#POST
#Consumes("application/xml")
public Response post(String content) {
URI createdUri = ...
String createdContent = create(content);
return Response.created(createdUri)
.entity(Entity.text(createdContent)).build();
}
The above failed for me also. But you are not wrong in saying
...several data types are by default supported
as they are. To get your example to work, simply change the Entity.text("someContent") to simply "someContent"
return Response.created(createdUri).entity("someContent").build();
And just for completeness, client side usage might look something like
Response response = webTarget.request().post(Entity.text("Hello World"));
which works just fine.
Second Issue:
Up until (I believe) Jersey 2.9, the jersey-media-json-jackson module is not auto-configured. So with 2.6, we need to set up the configuration either through package scanning in the web.xml or in the Application subclass. Either way, a web.xml is required. As stated here in regards to a 2.x servlet environment, which Tomcat 6 is.
In Servlet 2.5 environment, you have to explicitly declare the Jersey container Servlet in your Web application's web.xml deployment descriptor file.
So to scan for the JSON provider classes, you should specify the package in the jersey.config.server.provider.packages init-param. An example web.xml would be something like this
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<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>
thepackage.of.your.resources,
org.codehaus.jackson.jaxrs <!-- Jackson providers -->
</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>
</web-app>
You are also allowed to use an Application subclass (which ResourceConfig extends from). We just need to specify it in the web.xml. An example configuration might be something like
public class MyApplication extends ResourceConfig {
public MyApplication() {
register(JacksonFeature.class);
packages("thepackage.of.your.resources");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>MyApplication</servlet-name>
<servlet-class>
org.glassfish.jersey.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>jersey2.tomcat6.MyApplication</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>MyApplication</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
</web-app>
Note: All of this was tested against your same environment, besides using Eclipse. I am using Netbeans, though it shouldn't make any difference. Also the only Maven dependencies I needed were
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>
</dependencies>
<jersey.version>2.6</jersey.version>
On another note, to simplify development, I just created a simple Maven archetype with the following coordinates
GroupId: org.glassfish.jersey.archetypes
ArtifactId: jersey-quickstart-webapp
Version: 2.6
You can also see Creating a New Project from Maven Archetype
As far as the text/plain format, does this work?
return Response.created(createdUri).type(MediaType.TEXT_PLAIN).entity("someContent").build();
For JSON output, I have these dependencies
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
as well as a jaxb implementation. Any will do, I use
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
</dependency>
I also define an object mapper provider, though I'm not 100% sure that it's required (unless you want to customize):
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector;
#Provider
public class ObjectMapperProvider implements ContextResolver<ObjectMapper> {
ObjectMapper mapper;
public ObjectMapperProvider() {
mapper = new ObjectMapper();
mapper.configure( SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false );
mapper.configure( SerializationFeature.INDENT_OUTPUT, true );
mapper.configure( SerializationFeature.WRITE_NULL_MAP_VALUES, true );
mapper.configure( SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, true );
mapper.setAnnotationIntrospector( new JaxbAnnotationIntrospector(TypeFactory.defaultInstance()) );
}
#Override
public ObjectMapper getContext(Class<?> type) {
return mapper;
}
}
Also, I think you need to register the Jackson feature:
#ApplicationPath("")
public class Application extends ResourceConfig {
public Application() {
register( JacksonFeature.class );
}
}
I should note that this is all configured using Jersey 2.11.
In my case, I added the jersey-media-json-jackson dependency. It worked for me.
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.20</version>
</dependency>