What is wrong with my JAX-RS configuration? - java

SOLVED: The problem was something related to my context name, it was defined as "Application" but my browser was opening with "application", and this capital A was the key to solve the issue.
Can anyone please help me with this? I can't get JAX-RS to work, I am using WildFly 8.1.0.Final and I've set my project up using JBoss Forge 2
Take a loot at my files by now, as I did not get any console error
pom.xml
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
RestApplication.java
import javax.ws.rs.core.Application;
import javax.ws.rs.ApplicationPath;
#ApplicationPath("/api")
public class RestApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
return new HashSet<Class<?>>(Arrays.asList(TestEndpoint.class));
}
}
TestEndpoint.java
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("/test")
public class TestEndpoint {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getString() {
return "worked";
}
}
I tried to access it by
http://localhost:8080/application/api/test
but I got a 404 error page.
Thanks in advance

Related

Jax-rs annotation Path is not work in java spring boot?

I have spring boot application with starter version 2.1.16, and spring-boot-starter-web dependency. So, i want use javax.ws.rs-api library, and add dependency:
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1.1</version>
</dependency>
So when i create controller, and add #Path, #Get - i don't get answer from the server (404 not found). How makes it work?
package com.example.test;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.ext.Provider;
#RestController
public class MyController {
//Doesn't work (404 not found
#GET
#Path("/my_test")
public String check() {
return "hi!";
}
//Work
#RequestMapping("/my_test2")
public String check2() {
return "hi2!";
}
}
Add the following dependency in your pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
</dependencies>
if you use spring boot starter version 2.1.16, you will normally have a parent pom which will also define the default version for the above dependency.
Then replace #RestController with #Path("/") from package javax.ws.rs.Path
Now it should be working.
Keep in mind your embedded server now, will be jersey instead of default tomcat.
Edit: Also as found from the author of the question another change is needed to register a ResourceConfig. This is also described here in the official documentation.
In addition to the post above, you need to add the config class:
#Configuration
public class JerseyConfig {
#Bean
public ResourceConfig resourceConfig(MyController myController) {
ResourceConfig config = new ResourceConfig();
config.register(myController);
return config;
}
}

404 not found error shows when i run as java application [duplicate]

This question already has answers here:
Spring Boot does not honor #WebServlet
(3 answers)
Closed 12 months ago.
here is my servlet class
package login.example;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
#WebServlet(name = "LogoutServlet", urlPatterns = {"/LogoutServlet"})
public class LogoutServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public LogoutServlet() {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
PrintWriter out = response.getWriter();
response.setContentType("text/html");
HttpSession session = request.getSession();
session.invalidate();
out.println("Thank you,you are successfully logged out");
out.close();
}
here is web.xml
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>servlet-api</artifactId>
<version>6.0.39</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
</dependency>
}
in springboot project i have to run as java application but it gives 404 error,while when i run as run on server it totally works..what should i do?
I think you build the project as WAR, in this case the right way is to start the application in a servlet container(such as Tomcat), and not run as java application.

Failing JUnit tests for embedded Fongo DB

I have a Spring Boot application which use MongoDB. I would like to use the embedded FongoDB for my JUnit tests. I follow some articles, for example:
http://dontpanic.42.nl/2015/02/in-memory-mongodb-for-unit-and.html
My Fongo test configuration looks like
package com.myproject.rest;
import com.github.fakemongo.Fongo;
import com.mongodb.Mongo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
#Profile("test")
#ComponentScan(basePackages = "com.myproject.service.data")
#EnableMongoRepositories(basePackages = "com.myproject.service.data.repository")
#Configuration
public class MongoTestConfig extends AbstractMongoConfiguration {
#Override
protected String getDatabaseName() {
return "demo-test";
}
#Bean
#Override
public Mongo mongo() {
return new Fongo("mongo-test").getMongo();
}
}
I have this dependency for that:
<dependency>
<groupId>com.github.fakemongo</groupId>
<artifactId>fongo</artifactId>
<version>2.1.0</version>
<scope>test</scope>
</dependency>
I would like to test my services which autowired a repository interface which extends MongoRepository
package com.myproject.service.data.repository;
import com.myproject.service.data.entity.JournalData;
import org.springframework.data.mongodb.repository.MongoRepository;
import java.util.List;
public interface JournalRepository extends MongoRepository<JournalData, String> {
#Override
public List<JournalData> findAll(Iterable<String> ids);
}
My tests class are inherited from the class below:
package com.myproject.rest;
import com.lordofthejars.nosqlunit.mongodb.MongoDbRule;
import cz.csas.services.commons.api.RequestMetadata;
import org.junit.Before;
import org.junit.Rule;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static com.lordofthejars.nosqlunit.mongodb.MongoDbRule.MongoDbRuleBuilder.newMongoDbRule;
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
#PowerMockIgnore({"javax.xml.*", "org.xml.*", "org.w3c.*", "javax.management.*", "javax.net.ssl.*"})
#PrepareForTest({RequestMetadata.class})
#ActiveProfiles("test")
public class EndpointTestContext {
#Autowired
protected MockMvc mockMvc;
//#Rule
//public MongoDbRule mongoDbRule = newMongoDbRule().defaultSpringMongoDb("demo-test");
#Before
public void setup() {
mockStatic(RequestMetadata.class);
when(RequestMetadata.builder()).thenCallRealMethod();
RequestMetadata m = RequestMetadata.builder()
.workingMode("TEST")
.build();
when(RequestMetadata.getMetadata()).thenReturn(m);
}
}
But when I run the Maven tests I recieve the following:
Caused by: java.lang.NoClassDefFoundError: Could not initialize class com.mongodb.MongoClientOptions
at com.mongodb.MockMongoClient.create(MockMongoClient.java:42)
at com.github.fakemongo.Fongo.createMongo(Fongo.java:175)
at com.github.fakemongo.Fongo.<init>(Fongo.java:88)
at com.github.fakemongo.Fongo.<init>(Fongo.java:75)
at com.github.fakemongo.Fongo.<init>(Fongo.java:67)
at com.myproject.rest.MongoTestConfig.mongo(MongoTestConfig.java:30)
at com.myproject.rest.MongoTestConfig$$EnhancerBySpringCGLIB$$bf18b1d4.CGLIB$mongo$1(<generated>)
at com.myproject.rest.MongoTestConfig$$EnhancerBySpringCGLIB$$bf18b1d4$$FastClassBySpringCGLIB$$3ab8bfd7.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358)
at com.myproject.rest.MongoTestConfig$$EnhancerBySpringCGLIB$$bf18b1d4.mongo(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
... 115 common frames omitted
Can anyone suggest how to fix it? Thank you in advance.
Fongo can't find class from mongo-java-driver artifact. It declares
<!-- https://mvnrepository.com/artifact/org.mongodb/mongo-java-driver -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.4.2</version>
</dependency>
as provided dependency. You should have mongo-java-driver on your test classpath. Most probably
<scope>runtime</scope>
or test will be enough for you.
Check if you have multiple version of mongo java driver (version conflicts). To check this, you can use mvn dependency tree to trace the path from where each jar is coming to your project.
mvn dependency:tree
Just need to find out the right version on mongo java driver and make sure you are not having version conflicts. I have used spring data and used fongo to write in-memory test case for mongodb queries.
<fongo-version>1.6.3</fongo-version>
<spring-data-mongodb-version>1.7.2.RELEASE</spring-data-mongodb-version>
<spring-framework-version>4.1.5.RELEASE</spring-framework-version>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>${spring-data-mongodb-version}</version>
</dependency>
<dependency>
<groupId>com.github.fakemongo</groupId>
<artifactId>fongo</artifactId>
<version>${fongo-version}</version>
<scope>test</scope>
</dependency>
Version conflict can come from may source (can confirm using above mvc dependency:tree command, one such source is mongobee, so if you are using it, please exclude mongo-java-drive by using exclusion
<dependency>
<groupId>com.github.mongobee</groupId>
<artifactId>mongobee</artifactId>
<version>${mongobee-version}</version>
<exclusions>
<exclusion>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
</exclusion>
</exclusions>
</dependency>

no listing appears using swagger on jersey 2 with grizzly

I have setup swagger on jersey 2 and grizzly (no web.xml). I am able to access the swagger page however my API resources do not appear.
My main file is seen below
`
package com.beraben.jersey.test;
import com.wordnik.swagger.jaxrs.config.BeanConfig;
import java.net.URI;
import org.glassfish.grizzly.http.server.CLStaticHttpHandler;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
/**
*
* #author Evan
*/
public class jerseyTestMain {
/**
* #param args the command line arguments
*/
public static final String BASE_URI = "http://localhost:8080/myapp/";
public static HttpServer startServer() {
// create a resource config that scans for JAX-RS resources and providers
// in com.example.rest package
final ResourceConfig rc = new ResourceConfig().packages("com.beraben.jersey.test", "com.wordnik.swagger.jersey.listing");
BeanConfig config = new BeanConfig();
config.setResourcePackage("com.beraben.jersey.test");
config.setVersion("1.0.0");
config.setScan(true);
// create and start a new instance of grizzly http server
// exposing the Jersey application at BASE_URI
return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
}
public static void main(String[] args) throws InterruptedException {
final HttpServer server = startServer();
CLStaticHttpHandler staticHttpHandler = new CLStaticHttpHandler(jerseyTestMain.class.getClassLoader(), "swagger-ui/");
server.getServerConfiguration().addHttpHandler(staticHttpHandler, "/docs");
Object syncObj = new Object();
synchronized (syncObj) {
syncObj.wait();
}
}
}
`
I also have a API setup seen below
package com.beraben.jersey.test;
import com.wordnik.swagger.annotations.Api;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
/**
*
* #author Evan
*/
#Path("myresource")
#Api(value = "/myresource")
public class MyResource {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getIt(){
return "Got it!";
}
}
I have no problem using the API it returns correctly.
But for some reason I cant get swagger to show details about the API calls, is there something i need to do more to get it to show details about the existing API in my code?
My static files are copied from the sample project
jersey2-grizzly2-swagger-demo
Also for reference, here is my pom file (not slight difference from the demo project is I don't use dependencyManagment to get jersey-bom instead i reference it directly).
<?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>com.beraben</groupId>
<artifactId>jersey-test</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.archetypes</groupId>
<artifactId>jersey-quickstart-grizzly2</artifactId>
<version>2.22.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>2.22.2</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
<version>2.22.2</version>
</dependency>
<dependency>
<groupId>com.wordnik</groupId>
<artifactId>swagger-jersey-jaxrs_2.10</artifactId>
<version>1.3.13</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>
After looking at the google forms, it turns out that standalone version of swagger does not actually work.
I created a separate maven web app and added my jersey project as dependencies. This worked after fiddling around with the swagger version that matched the jersey version I was using.

MessageBodyWriter not found for media type=application/json with GF4 and Jackson

I got the following error message every time I try to call my REST service
[2016-09-01T16:27:37.782+0200] [Payara 4.1] [SEVERE] [] [org.glassfish.jersey.message.internal.WriterInterceptorExecutor] [tid: _ThreadID=28 _ThreadName=http-listener-1(3)] [timeMillis: 1472740057782] [levelValue: 1000] [[MessageBodyWriter not found for media type=application/json, type=class xxx.JsonClass, genericType=class xxx.JsonClass.]]
Here's the REST service (stripped to the relevant part):
import javax.ejb.EJB;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
#Path("/service")
public class Service {
#GET
#Path("/callme")
#Produces(MediaType.APPLICATION_JSON)
public JsonClass callme(//
#QueryParam("test") final String test, //
....) {
return new JsonClass();
}
}
The JSON Class
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
public class JsonClass {
private String test;
public JsonClass(final String test....) {
...
}
#JsonProperty
public String getTest() {
return this.test;
}
}
POM.xml (interesting parts)
<!-- DO NOT change the scope for jersey: https://java.net/jira/browse/JERSEY-1941 -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.8</version>
<scope>provided</scope>
</dependency>
My setup is:
JDK8/JEE7 (build 1.8.0_51-b16)
Glassfish 4.1 Payara
Maven 3.2.5
This is what I tried so far:
MessageBodyWriter not found for media type=application/json -> Doesn't work because I run into a problem with Glassfish 4 and Weld (https://java.net/jira/browse/JERSEY-1941)
SEVERE: MessageBodyWriter not found for media type=application/json, type=class com.jersey.jaxb.Todo, genericType=class com.jersey.jaxb.Todo -> As seen in the POM.xml above it's already included and does not work
https://java.net/jira/browse/JERSEY-2715 -> Annotation #Produces is already there and doesn't help either
Obtaining "MessageBodyWriter not found for media type=application/json" trying to send JSON object through JAX-RS web service - GENSON with #XmlAttribute had not the desired effect
I tried to keep the JSON object as simple as possible to avoid problems with arrays and complex objects -> No change
I still think it's a dependency problem here. However I'm out of ideas what could be the problem.
Unfortunately my last post was marked as duplicate although the problem and the solution was different. Therefore I'm posting a new question with the two solutions to hopefully help you avoid head banging at the table for several hours.
Preferred solution:
Apparently GF4 ships with MoxyJson which I didn't want to use. To integrate your own dependency - in my case Jackson - you need to disable the MoxyJson with the below code.
#ApplicationPath("/")
public class ApplicationConfig extends Application {
/**
* {#inheritDoc}
*/
#Override
public Map<String, Object> getProperties() {
final Map<String, Object> properties = new HashMap<String, Object>();
properties.put("jersey.config.server.disableMoxyJson", true);
return properties;
}
}
Then add your own dependencies, e.g. in my case only those two because the others are referenced by another lib I use.
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.6.2</version>
</dependency>
Finally I made the mistake of not setting a value to the #JsonProperty annotations which will cause a No MessageBodyWriter found exception. To avoid that use the following ony relevant getters of your class.
#JsonProperty("randomName")
public String getRandomName(){
...
}
Alternative:
Worse than above you'll need to disable MoxyJson, register each service individually, and fix a Bug when using ResourceConfig of GF.
#ApplicationPath("/")
public class ApplicationConfig extends ResourceConfig {
/**
* The default constructor.
*/
public ApplicationConfig() {
// Disable Moxy and use Jackson
this.property(ServerProperties.MOXY_JSON_FEATURE_DISABLE, true);
// Register own provider classes
this.register(Fully.Qualified.Path.To.Your.Service.class);
// Register Jackson provider
// Workaround for GF4.1 bug for details: https://java.net/jira/browse/GLASSFISH-21141
final ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JaxbAnnotationModule());
this.register(new JacksonJaxbJsonProvider(mapper, JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS));
}
}
You'll need an additional dependency for the ResourceConfig class.
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.main.extras</groupId>
<artifactId>glassfish-embedded-all</artifactId>
<version>4.1.1</version>
<scope>provided</scope>
</dependency>
Finally the same as above - be aware to use #JsonProperty with a set value.

Categories