I'm running Unit Test to test my RESTful web service run with Grizzly, and get the following exception.
javax.ws.rs.NotFoundException: HTTP 404 Not Found
at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:917)
at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:770)
at org.glassfish.jersey.client.JerseyInvocation.access$500(JerseyInvocation.java:90)
at org.glassfish.jersey.client.JerseyInvocation$2.call(JerseyInvocation.java:671)
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:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:422)
at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:667)
at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:396)
at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:296)
at com.example.MyResourceTest.testGetIt(MyResourceTest.java:45)
The Unit Test
package com.example;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.UriBuilder;
import java.net.URI;
import static org.junit.Assert.assertEquals;
public class MyResourceTest {
public static final URI BASE_URI = UriBuilder.fromUri("http://localhost").port(8080).build();
private HttpServer server;
private WebTarget target;
#Before
public void setUp() throws Exception {
ResourceConfig rc = new ResourceConfig();
server = GrizzlyHttpServerFactory.createHttpServer(BASE_URI, rc);
server.start();
Client c = ClientBuilder.newClient();
target = c.target(BASE_URI);
}
#After
public void tearDown() throws Exception {
server.stop();
}
/**
* Test to see that the message "Got it!" is sent in the response.
*/
#Test
public void testGetIt() {
String responseMsg = target.path("myresource").request().get(String.class); // <--- line 45 in exception!!!
assertEquals("Got it!", responseMsg);
}
}
And the REST service
package com.example;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
/**
* Root resource (exposed at "myresource" path)
*/
#Path("myresource")
public class MyResource {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getIt() {
return "Got it!";
}
}
And dependencies from POM.xml
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.grizzly</groupId>
<artifactId>grizzly-http-server</artifactId>
<version>2.3.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
<version>2.5.1</version>
</dependency>
Thanks in advance!!!
I FIXED IT!
I needed this:
ResourceConfig rc = new ResourceConfig(MyResource.class); //This is resource class
instead of:
ResourceConfig rc = new ResourceConfig();
And now I'm using only these dependencies in POM.xml
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-servlet</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
Thanks, for attention!
Related
I am having log4j2 with slf4j but getting same log message.
Provided the sample code. Getting Mutable Log Event in Argument Capture Log Event object.
Count is giving correct but same message gets repeated in when I call getAllValues() method.
Using Mockito, junit and log4j2. I debugged a lot but could find that what should be change to get correct log message in test class. I can see some other alternatives to test the same behaviour but I want to know where is the error in this piece of code.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ApplicationLog {
Logger logger = LoggerFactory.getLogger(ApplicationLog.class);
public void sayHi(){
//System.out.println("hi");
logger.warn("Say Hi");
logger.warn("Say Hello");
}
}
Test class
import static org.hamcrest.CoreMatchers.is;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.Configurator;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.*;
import org.mockito.runners.MockitoJUnitRunner;
#RunWith(MockitoJUnitRunner.class)
public class ApplicationLogTest {
private ApplicationLog applicationLog = new ApplicationLog();
#Mock
private Appender mockAppender;
#Captor
private ArgumentCaptor<LogEvent> captorLoggingEvent;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
final Configuration config = ctx.getConfiguration();
Mockito.reset(mockAppender);
config.getRootLogger().addAppender(mockAppender, null, null);
Mockito.when(mockAppender.getName()).thenReturn("MockAppender");
Mockito.when(mockAppender.isStarted()).thenReturn(true);
Mockito.when(mockAppender.isStopped()).thenReturn(false);
ctx.updateLoggers();
}
#After
public void teardown() {
((LoggerContext) LogManager.getContext(false)).getConfiguration().getRootLogger().removeAppender(null);
}
#Test
public void firstTest(){
Configurator.setRootLevel(Level.TRACE);
applicationLog.sayHi();
verify(mockAppender, times(2)).append((LogEvent) captorLoggingEvent.capture());
String message = captorLoggingEvent.getAllValues().get(0).getMessage().getFormattedMessage();
**// Not getting Say Hi but getting Say Hello**
assertThat(message, is("Say Hi"));
}
}
Dependencies
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${org.log4j-version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${org.log4j-version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${org.log4j-version}</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
In another project I have an embedded Jetty server and after updating the Jetty version to anything above 9.4.29 I got an error.
So I went to create a new project to start finding out what caused this error.
However... I didn't even get to the same error as the new project fails with:
javax.servlet.ServletException: org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher-7b2bbc3==org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher#b539e71f{jsp=null,order=-1,inst=true,async=true,src=EMBEDDED:null,STARTED}
at jetty.test.JettyTest.hello(JettyTest.java:78)
Caused by: java.lang.IllegalArgumentException: RESTEASY003900: Unable to find a public constructor for provider class jetty.test.JettyTest$TestApplication
at jetty.test.JettyTest.hello(JettyTest.java:78)
I have the feeling that I'm missing something obviously... Any help is appreciated.
Thanks
My test class:
package jetty.test;
import static io.restassured.RestAssured.given;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.specification.RequestSpecification;
import java.util.HashSet;
import java.util.Set;
import javax.servlet.ServletConfig;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.eclipse.jetty.server.Server;
import org.junit.jupiter.api.Test;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher;
public class JettyTest {
#Path("/health")
public class HealthResource {
#GET
#Path("/")
#Produces(MediaType.TEXT_PLAIN)
public Response getHealth() {
return Response.ok().entity("good").build();
}
}
#ApplicationPath("/api")
public class TestApplication extends Application {
HashSet<Object> singletons = new HashSet<>();
public TestApplication() {
super();
}
public TestApplication(#Context ServletConfig servletConfig) {
singletons.add(HealthResource.class);
}
#Override
public Set<Class<?>> getClasses() {
HashSet<Class<?>> set = new HashSet<>();
set.add(HealthResource.class);
return set;
}
#Override
public Set<Object> getSingletons() {
return singletons;
}
}
#Test
public void hello() throws Exception {
Server server = new Server(8082);
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
server.setHandler(context);
final ServletHolder servletHolder = new ServletHolder(new HttpServletDispatcher());
servletHolder.setInitParameter("resteasy.scan", "true");
servletHolder.setInitParameter("resteasy.servlet.mapping.prefix", "/api/*");
servletHolder.setInitParameter("javax.ws.rs.Application", TestApplication.class.getName());
context.addServlet(servletHolder, "/api/*");
server.start();
RequestSpecification spec = new RequestSpecBuilder()
.setBaseUri("http://localhost:8082/").build();
given().spec(spec).when().get("/api/res").then().statusCode(200);
}
}
And my 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>org.test</groupId>
<artifactId>JettyTestProject</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.0</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.4.43.v20210629</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>9.4.43.v20210629</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.12.4</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-servlet-initializer</artifactId>
<version>4.7.1.Final</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
</project>
The definition you have of ...
public class JettyTest {
....
public class TestApplication extends Application {
means you cannot create TestApplication without first creating the JettyTest.
Just change the inner class to static, that should be enough.
public class JettyTest {
....
public static class TestApplication extends Application {
I had a test case to test the jersey 2.x rest service.. But got NullPointerException.. Seems to me there is a jar issue between jsr311 and javax.ws.rs-api . I didn't find any jsr311 with any dependencies.. Not sure why the servlet is taking is refering jsr311.jar
Below are my code changes
HelloWorldServiceTest.java
package test;
import static org.junit.Assert.assertEquals;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Application;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
import org.glassfish.jersey.test.DeploymentContext;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.ServletDeploymentContext;
import org.glassfish.jersey.test.ServletDeploymentContext.Builder;
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
import org.glassfish.jersey.test.spi.TestContainerException;
import org.glassfish.jersey.test.spi.TestContainerFactory;
import org.junit.Test;
import com.mkyong.rest.HelloWorldService;
import rest.RestApplication;
public class HelloWorldServiceTest extends JerseyTest{
#Path("hello")
public static class HelloResource {
#GET
public String getHello() {
return "Hello World!";
}
}
#Override
protected Application configure() {
// TODO Auto-generated method stub
return new ResourceConfig(HelloWorldService.class );
}
#Override
protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
return new GrizzlyWebTestContainerFactory();
}
#Override
protected ServletDeploymentContext configureDeployment() {
return ServletDeploymentContext.forPackages(HelloWorldService.class.getPackage().getName()).build();
//return ServletDeploymentContext.forServlet(new ServletContainer(new ResourceConfig(HelloWorldService.class))).build();
}
#Test
public void testSingleNode() throws Exception {
final String hello = target("hello").path("Test").request().get(String.class);
System.out.println("Response"+ hello);
assertEquals("Jersey say : Test", hello);
}
}
pom.xml
<dependencies>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework</groupId>
<artifactId>jersey-test-framework-core</artifactId>
<version>2.13</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>2.13</version>
</dependency>
</dependencies>
Below is my exception i got
java.lang.NoSuchMethodError: org.glassfish.jersey.internal.util.collection.Values.lazy(Lorg/glassfish/jersey/internal/util/collection/Value;)Lorg/glassfish/jersey/internal/util/collection/Value;
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:346)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:372)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:218)
at org.glassfish.grizzly.servlet.FilterChainImpl.doFilter(FilterChainImpl.java:147)
at org.glassfish.grizzly.servlet.FilterChainImpl.invokeFilterChain(FilterChainImpl.java:106)
at org.glassfish.grizzly.servlet.ServletHandler.doServletService(ServletHandler.java:221)
at org.glassfish.grizzly.servlet.ServletHandler.service(ServletHandler.java:169)
at org.glassfish.grizzly.http.server.HttpHandler$1.run(HttpHandler.java:219)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
at java.lang.Thread.run(Unknown Source)
I've googled and tried but I cant get Providers to work in my project.
POM.XML:
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.22.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.22.1</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-servlet-api</artifactId>
<version>9.0.0.M1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.22.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>1.19</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
My Filter:
package xxxxxxx
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.DatatypeConverter;
#Provider
public class BasicAuthFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext)
throws IOException {
String authorization = requestContext.getHeaderString("Authorization");
if (!auth(authorization)) {
requestContext.abortWith(Response
.status(Response.Status.UNAUTHORIZED)
.entity("User cannot access the resource.")
.build());
}
}
private Boolean auth(String authorization)
throws UnsupportedEncodingException {
if (authorization != null && authorization.startsWith("Basic")) {
String base64Credentials = authorization
.substring("Basic".length()).trim();
byte[] decoded = DatatypeConverter
.parseBase64Binary(base64Credentials);
final String[] values = new String(decoded, "UTF-8").split(":", 2);
if (values.length == 2 && values[0].equals("usuario")
&& values[1].equals("senha")) {
return true;
}
}
return false;
}
}
My ResourceConfig class:
import javax.ws.rs.ApplicationPath;
import org.glassfish.jersey.server.ResourceConfig;
import xxx.providers.BasicAuthFilter;
import xxx.resource.LogParserResource;
#ApplicationPath("rest")
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
register(BasicAuthFilter.class);
register(MyResource.class);
}
}
Filter is not triggered. Anything wrong in my configuration?
WEB.XML is empty and the Resource is working fine. Any suggestions??
Thanks.
i noticed, that this dependency is not the version of the other ones:
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>1.19</version>
</dependency>
you could try to use:
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.22.1</version>
</dependency>
and then notice the documentation:
Important
Servlet 2.x API does not provide a way how to programmatically read
the filter mappings. To make application deployed using filter work
correctly, either Servlet 3.x container must be used
(jersey-container-servlet instead of jersey-container-servlet-core),
or the context path of the app needs to be defined using init
parameter jersey.config.servlet.filter.contextPath.
see: https://jersey.java.net/documentation/latest/deployment.html#deployment.servlet
I am creating a Spring MVC Controller test. Compiler is showing errors for methods shown below in bold. Am I missing some library or something in my code? Any suggestions?
I am using following dependencies:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MockMvcBuilder;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import com.zerosolutions.view.form.LoginCredentials;
#RunWith(value=SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration("classpath:dispatcher-servlet.xml")
public class TestingFrontController {
#Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
#Before
public void setUp(){
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
#Test
public void getLoginSignupPage() throws Exception{
this.mockMvc.perform(**get**("/"))
.andExpect(status().isOk())
.andExpect(forwardedUrl("login"))
.andExpect(model().attribute("loginCred", **any**(LoginCredentials.class)));
}
}
add following to import these methods
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;