org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=text/plain; charset=ISO-8859-1 - rest

I am trying to call rest service using restassured framework - getting this exception.
org.glassfish.jersey.server.ServerRuntime$Responder mapException
WARNING: WebApplicationException cause:
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=text/plain; charset=ISO-8859-1, type=class com.digicel.selfcare.service.services.beans.request.FacebookNewsFeedRequest, genericType=class com.digicel.selfcare.service.services.beans.request.FacebookNewsFeedRequest.
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:207)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:139)
at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundReadFrom(MappableExceptionWrapperInterceptor.java:72)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:139)
at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1109)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:851)
at org.glassfish.jersey.server.ContainerRequest.readEntity(ContainerRequest.java:253)
at org.glassfish.jersey.server.internal.inject.EntityParamValueFactoryProvider$EntityValueFactory.provide(EntityParamValueFactoryProvider.java:96)
at org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:81)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInv
#Path("social/")
public class MyService{
#POST
#Path("facebook/feeds")
#Produces(MediaType.APPLICATION_JSON)
public List<FacebookNewsFeedResult>getFacebookNewsFeed(FacebookNewsFeedRequest request, #Context HttpServletRequest httpReq)
}
This my jUnit : using restassured
#Test
public void getFacebookNewsFeedTest() throws Exception
{
final String resource = "social/facebook/feeds";
String jsonContent = "{\"feedId\": \"100\",\"pull\": \"true\"}";
expect().spec(okResponse).with().headers(this.authorizedHeaders).content(ContentType.JSON).content(jsonContent).post(selfCareServiceTest.buildURLForResource(resource));
}

Related

Unit Testing Rest Services with Spring Boot and JUnit

I have a basic SpringBoot app. using Spring Initializer, JPA, embedded Tomcat, Thymeleaf template engine, and package as an executable JAR file. I've defined this Rest method to get a User
#GetMapping(path = "/api/users/{id}",
consumes = "application/json",
produces = "application/json")
public ResponseEntity<User> getUser
(HttpServletRequest request,
#PathVariable long id) {
User user = checkAccess(request, id);
return ResponseEntity.ok(user);
}
I've created this Junit to test it
#ContextConfiguration(classes={TestSystemConfig.class})
#RunWith(SpringRunner.class)
#WebMvcTest(UserResourceController.class)
public class UserResourceControllerTests {
#Autowired
private MockMvc mvc;
#MockBean
private UserResourceController UserResourceController;
#Test
public void getUser() throws Exception {
mvc.perform(get("/api/users/1")
.with(user("pere.peris#gmail.com").password("password"))
.contentType(APPLICATION_JSON))
.andExpect(status().isOk());
}
}
But I got this error when I run the test:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalArgumentException: Name for argument type [long] not available, and parameter name information not found in class file either.
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:71)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:166)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)
The reason is because you are mocking your controller. This is not necessary when you have #WebMvcTest(UserResourceController.class)
This should work.
#ContextConfiguration(classes={TestSystemConfig.class})
#RunWith(SpringRunner.class)
#WebMvcTest(UserResourceController.class)
public class UserResourceControllerTests {
#Autowired
private MockMvc mvc;
#Test
public void getUser() throws Exception {
mvc.perform(get("/api/users/1")
.with(user("pere.peris#gmail.com").password("password"))
.contentType(APPLICATION_JSON))
.andExpect(status().isOk());
}
}

Attempt to POST to a servlet results in HTTP Status 404 - Could not find resource for relative

I've a HTML form:
<form action="rest/ws/addNote" method="post">
I'm trying to POST to this servlet:
#WebServlet("/ws")
public class AddNote extends HttpServlet {
#POST
#Path("/addNote")
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// ...
}
}
But I keep getting
HTTP Status 404 - Could not find resource for relative : /ws/addNote of full path: http://localhost:8080/project/rest/ws/addNote
You are sending a post request for that you should have a post request handler method there in your servlet. I am assuming you are not using any REST framework. Then your servlet should be:
#WebServlet("/rest/ws/addNote")
public class AddNote extends HttpServlet {
private static final long serialVersionUID = 1L;
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
........
Or if you are already using any REST frameworks like Jersy, don't use a servlet here.Try some examples
Update
since you are using REST try following instead of servlet:
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
#Path("/ws")
public class AddNote {
#POST
#Path("/addNote")
public Response addUser(
#FormParam("name") String name,
#FormParam("age") int age) {
.........
Here I assumed in your web.xml, the REST controller servlet mapping is /rest/* and your html <form> having <input> tags with names name,age, then the will be passed into the corresponding method arguments as above.
Full example you can see here

Jersey JAX-RS Glassfish 4 throwing java.lang.IllegalStateException

I am creating a simple RESTful service
#Path("/book")
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
#Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
#Stateless
public class RestBookService {
#PersistenceContext(unitName="bookPU")
private EntityManager em;
#Context
protected UriInfo uriInfo;
#POST
public Response createBook(Book book) {
if (book == null)
throw new BadRequestException();
em.persist(book);
URI bookUri = uriInfo.getAbsolutePathBuilder().path(book.getId() + "").build();
return Response.created(bookUri).build();
}
}
The Book is simple JPA entity
#Entity
#XmlRootElement
public class Book {
static Logger log = Logger.getLogger(Book.class.getName());
public static final String FIND_ALL = "Book.find_all";
#Id
#GeneratedValue
private int id;
#Column(nullable=false)
private String title;
#Column
private Float price;
}
//Just giving a relevant code. There are getters/setters and the constructor
I am deploying the service using Maven on Glassfish 4.1
I am using
Jersey Container 2.13
Hibernate 4.3.5 Final
Mysql 5.1
and when I try to create a book using cURL as follows
curl -X POST --data-binary "<book><price>12.5</price><title>Book Title</title></book>" -H "Content-Type: application/xml" http://localhost:8080/book-service/rs/book -v
It is throwing following exception.
StandardWrapperValve[jersey-serlvet]: Servlet.service() for servlet jersey-serlvet threw exception
java.lang.IllegalStateException: Not inside a request scope.
at jersey.repackaged.com.google.common.base.Preconditions.checkState(Preconditions.java:149)
at org.glassfish.jersey.process.internal.RequestScope.current(RequestScope.java:228)
at org.glassfish.jersey.process.internal.RequestScope.findOrCreate(RequestScope.java:156)
at org.jvnet.hk2.internal.MethodInterceptorImpl.invoke(MethodInterceptorImpl.java:74)
at org.jvnet.hk2.internal.MethodInterceptorInvocationHandler.invoke(MethodInterceptorInvocationHandler.java:62)
at com.sun.proxy.$Proxy239.getAbsolutePathBuilder(Unknown Source)
at com.services.bookrestservice.rest.RestBookService.createBook(RestBookService.java:44)
[There is another question similar to this but I have done exactly the same which is given in the answer still I am getting the exception. Also, I have gone through https://java.net/jira/browse/JERSEY-2241 but it seems to be in resolved state with the resolution as cannot reproduce. ]
Can somebody please help me.
EDIT1
I have changed from Stateless annotation to RequestScoped annotation as suggested by #HankCa. It is throwing following exception now.
'javax.persistence.TransactionRequiredException
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTxRequiredCheck(EntityManagerWrapper.java:161)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTransactionScopedTxCheck(EntityManagerWrapper.java:151)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.persist(EntityManagerWrapper.java:281)
at com.services.bookrestservice.rest.RestBookService.createBook(RestBookService.java:44)
'
Not sure why this exception because it is already in persistentcontext.
EDIT2
#HankCa suggested I did the following change.
Removed
#Context
protected UriInfo uriInfo;
And updated the method signature as
#POST
public Response createBook(Book book, #Context UriInfo uriInfo) {
And the service is working as expected. Thanks HankCa for your help.
Yes I stared at this one for far too long and my solution was as you found at Why is my Jersey JAX-RS server throwing a IllegalStateException about not being in RequestScope?. This was a year ago and I haven't hit it again (though I have been out of EJB land for a while) so I'll give it my best shot.
Specifically I would make these mods:
Add #RequestScoped
Put the #Context UriInfo uriInfo in the method or class. In the end i seemed to have gone in the method like:
This is code (and this is a line to separate the list from the code so the code shows as code!)
#Path("/user")
#Produces({ MediaType.APPLICATION_JSON })
#Consumes({ MediaType.APPLICATION_JSON })
#RequestScoped
public class UserResource {
...
#PermitAll
#POST
public Response signupUser(CreateUserRequest request, #Context UriInfo uriInfo) {
AuthenticatedUserToken token = userService.createUser(request, Role.authenticated);
verificationTokenService.sendEmailRegistrationToken(token.getUserId());
URI location = uriInfo.getAbsolutePathBuilder().path(token.getUserId()).build();
return Response.created(location).entity(token).build();
}
I hope that helps!
Cheers,
bbos

How to test SOAPAction header with Spring WS Test

My app is calling an external Soap WS using spring-ws's WebServiceTemplate, which I mock in my tests using MockWebServiceServer.
It works fine to simulate the response depending on the request payload.
But now I'd like to test which SOAP action is called. It should be defined in the "SOAPAction" HTTP header of the request.
I'm using Spring-WS 2.1.4.
Does anyone know if it's possible to test that and how?
Here is my test class :
public class MyWebServiceTest {
#Autowired
private WebServiceTemplate webServiceTemplate;
private MockWebServiceServer mockServer;
#Before
public void createServer() throws Exception {
mockServer = MockWebServiceServer.createServer(webServiceTemplate);
}
#Test
public void callStambiaWithExistingFileShouldSuccess() throws IOException {
Resource requestPayload = new ClassPathResource("request-payload.xml");
Resource responseSoapEnvelope = new ClassPathResource("success-response-soap-envoloppe.xml");
mockServer.expect(payload(requestPayload)).andRespond(withSoapEnvelope(responseSoapEnvelope));
//init job
//myService call the webservice via WebServiceTemplate
myService.executeJob(job);
mockServer.verify();
//some asserts
}
}
So what I want to test is the soap action called. So I want something like this in my test class :
mockServer.expect(....withSoapAction("calledSoapAction")).andRespond(...
Creating your own RequestMatcher is pretty straightforward:
public class SoapActionMatcher implements RequestMatcher {
private final String expectedSoapAction;
public SoapActionMatcher(String expectedSoapAction) {
this.expectedSoapAction = SoapUtils.escapeAction(expectedSoapAction);
}
#Override
public void match(URI uri, WebServiceMessage request)
throws IOException, AssertionError {
assertThat(request, instanceOf(SoapMessage.class));
SoapMessage soapMessage = (SoapMessage) request;
assertThat(soapMessage.getSoapAction(), equalTo(expectedSoapAction));
}
}
Usage
mockServer.expect(connectionTo("http://server/"))
.andExpect(new SoapActionMatcher("calledSoapAction"))
.andRespond(withPayload(...)));

JEE6 REST Service #AroundInvoke Interceptor is injecting a null HttpServletRequest object

I have an #AroundInvoke REST Web Service interceptor that I would like to use for logging common data such as the class and method, the remote IP address and the response time.
Getting the class and method name is simple using the InvocationContext, and the remote IP is available via the HttpServletRequest, as long as the Rest Service being intercepted includes a #Context HttpServletRequest in its parameter list.
However some REST methods do not have a HttpServletRequest in their parameters, and I can not figure out how to get a HttpServletRequest object in these cases.
For example, the following REST web service does not have the #Context HttpServletRequest parameter
#Inject
#Default
private MemberManager memberManager;
#POST
#Path("/add")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Member add(NewMember member) throws MemberInvalidException {
return memberManager.add(member);
}
I have tried injecting it directly into my Interceptor, but (on JBoss 6.1) it is always null...
public class RestLoggedInterceptorImpl implements Serializable {
#Context
HttpServletRequest req;
#AroundInvoke
public Object aroundInvoke(InvocationContext ic) throws Exception {
logger.info(req.getRemoteAddr()); // <- this throws NPE as req is always null
...
return ic.proceed();
I would like advice of a reliable way to access the HttpServletRequest object - or even just the Http Headers ... regardless of whether a REST service includes the parameter.
After researching the Interceptor Lifecycle in the Javadoc http://docs.oracle.com/javaee/6/api/javax/interceptor/package-summary.html I don't think its possible to access any servlet context information other than that in InvocationContext (which is defined by the parameters in the underlying REST definition.) This is because the Interceptor instance has the same lifecycle as the underlying bean, and the Servlet Request #Context must be injected into a method rather than the instance. However the Interceptor containing #AroundInvoke will not deploy if there is anything other than InvocationContext in the method signature; it does not accept additional #Context parameters.
So the only answer I can come up with to allow an Interceptor to obtain the HttpServletRequest is to modify the underlying REST method definitons to include a #Context HttpServletRequest parameter (and HttpServletResponse if required).
#Inject
#Default
private MemberManager memberManager;
#POST
#Path("/add")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Member add(NewMember member, #Context HttpServletRequest request, #Context HttpServletResponse response) throws MemberInvalidException {
...
}
The interceptor can then iterate through the parameters in the InvocationContext to obtain the HttpServletRequest
#AroundInvoke
public Object aroundInvoke(InvocationContext ic) throws Exception {
HttpServletRequest req = getHttpServletRequest(ic);
...
return ic.proceed();
}
private HttpServletRequest getHttpServletRequest(InvocationContext ic) {
for (Object parameter : ic.getParameters()) {
if (parameter instanceof HttpServletRequest) {
return (HttpServletRequest) parameter;
}
}
// ... handle no HttpRequest object.. e.g. log an error, throw an Exception or whatever
Another work around to avoid creating additional parameters in every REST method is creating a super class for all REST services that use that kind of interceptors:
public abstract class RestService {
#Context
private HttpServletRequest httpRequest;
// Add here any other #Context fields & associated getters
public HttpServletRequest getHttpRequest() {
return httpRequest;
}
}
So the original REST service can extend it without alter any method signature:
public class AddService extends RestService{
#POST
#Path("/add")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Member add(NewMember member) throws MemberInvalidException {
return memberManager.add(member);
}
...
}
And finally in the interceptor to recover the httpRequest:
public class RestLoggedInterceptorImpl implements Serializable {
#AroundInvoke
public Object aroundInvoke(InvocationContext ic) throws Exception {
// Recover the context field(s) from superclass:
HttpServletRequest req = ((RestService) ctx.getTarget()).getHttpRequest();
logger.info(req.getRemoteAddr()); // <- this will work now
...
return ic.proceed();
}
...
}
I'm using Glassfish 3.1.2.2 Jersey
For http header this works for me:
#Inject
#HeaderParam("Accept")
private String acceptHeader;
To get UriInfo you can do this:
#Inject
#Context
private UriInfo uriInfo;