I'm creating an WEB Api with Java and Jersey and now i get 415 status code on a POST request to my API.
The request made by Postman with the Header Content-type application/json
These images show my request
And that is my code.
package api;
import java.sql.SQLException;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import DAO.TransactionDAO;
import DAO.UsersDAO;
import Entity.Transaction;
import Entity.Users;
#Path("/users")
public class UsersController {
private UsersDAO dao;
private static final String CHARSET = ";charset=UTF-8";
#PostConstruct
private void init(){
this.dao = new UsersDAO();
}
#POST
#Path("/add")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.TEXT_PLAIN)
public int insert(Users user){
try{
return this.dao.add(user);
}
catch(Exception e){
e.toString();
return 0;
}
}
}
I found the error. My model didn't have an empty constructor. I just create it and work.
Related
I'm following this tutorial in order to learn how to code RESTful web services - tutorial. Here we are trying to send the status code 201 Created along with the posting of a new message through Postman. When I write the lines of code he writes at 4:47 I get an error in eclipse oxygen:
CREATED cannot be resolved or is not a field
I went through the documentation, but I couldn't find the correct way to type it. Tried to import more Response classes as well, but this didn't fix it.
This is the code where the problem occurs:
return Response.status(Status.CREATED)
.entity(newMessage)
.build();
And this is the whole class:
`import java.net.URI;
import java.util.List;
import javax.net.ssl.SSLEngineResult.Status;
import javax.ws.rs.BeanParam;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.core.Response.ResponseBuilder;
import org.hristo.javabrains.messenger.model.Message;
import org.hristo.javabrains.messenger.resources.beans.MessageFilterBean;
import org.hristo.javabrains.messenger.service.MessageService;
import com.sun.research.ws.wadl.Response;
#Path("messages")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public class MessageResource {
MessageService messageService = new MessageService();
#GET
public List<Message> getMessages(#BeanParam MessageFilterBean filterBean) {
if(filterBean.getYear() > 0) {
return messageService.getAllMessagesForYear(filterBean.getYear());
}
if(filterBean.getStart() >= 0 && filterBean.getSize() >= 0) {
return messageService.getAllMessagesPaginated(filterBean.getStart(), filterBean.getSize());
}
return messageService.getAllMessages();
}
#POST
public Response addMessage(Message message, #Context UriInfo uriInfo) {
Message newMessage = messageService.addMessage(message);
String newId = String.valueOf(newMessage.getId());
URI uri = uriInfo.getAbsolutePathBuilder().path(newId).build();
return Response.status(Status.CREATED)
.entity(newMessage)
.build();
}
#PUT
#Path("{messageId}")
public Message updateMessage(#PathParam("messageId") long messageId, Message message) {
message.setId(messageId);
return messageService.updateMessage(message);
}
#DELETE
#Path("{messageId}")
public Message removeMessage(#PathParam("messageId") long messageId) {
return messageService.removeMessage(messageId);
}
#GET
#Path("{messageId}")
public Message getMessage(#PathParam("messageId") long messageId) {
return messageService.getMessage(messageId);
}
#Path("{messageId}/comments")
public CommentResource getCommentResource() {
return new CommentResource();
} }
The Response import should be javax.ws.rs.core.Response and Status is a static inner class of Response. So either import the static Response.Status or just use Response.Status instead of just Status.
For more information, please refer to the javadoc.
I have a restful web service which is written by using spring. Now I want to call it from my android application.
Unfortunately I am familiar with retrofit.
This is one of my method in restful web service.
import com.example.service.RosterDetailService;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
#RestController
#RequestMapping(value = "/api/v1/roster")
public class RosterDetailManagement {
private final Logger logger = LoggerFactory.getLogger(RosterDetailManagement.class);
#Autowired
private RosterDetailService rosterDetailService;
#RequestMapping(value = "/details/getGuardRecords", method = RequestMethod.POST)
#ResponseBody
public List<Map<Object, Object>> getRosterDetailsByGuardEmailAndType(#RequestBody ObjectNode params) {
logger.info("-----------RosterDetailManagement, getRosterDetailsByGuardEmailAndType 1");
Map<Object, Object> response = new HashMap<>();
String guardEmail = params.get("guardEmail").asText();
String status = params.get("status").asText();
return rosterDetailService.getRosterDetailsByGuardEmailAndType(guardEmail, status);
}
}
Now I want detailed steps to call this restful web service in android.
Can anyone help me ?
I have a Jersey REST API that returns 204 No content instead of 404 when the entity to be returned back is null.
To address this issue, I'm currently planning to throw an exception within the resource method so that it could force Jersey to return 404 like below.
if (feature == null) throw new WebApplicationException(404);
But I have various REST URIs that suffer from the same problem. Is there a way to address all of them without touching each and every resource method?
My resource methods look like this:
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.example.webapi.domain.Feature;
import com.example.webapi.service.FeatureService;
#Component
#Path("features")
#Produces(MediaType.APPLICATION_JSON)
public class FeatureResource {
#Autowired
private FeatureService featureService;
#GET
public List<Feature> getFeatures() {
return featureService.listAllFeatures();
}
#GET
#Path("{featureCode}")
public Feature getFeature(#PathParam("featureCode") Integer featuresCode) {
return featureService.findFeatureByFeatureCode(featuresCode);
}
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Response addFeature(Feature feature, #Context UriInfo uriInfo) {
Integer id = (Integer) featureService.createFeature(feature);
return Response.created(uriInfo.getAbsolutePathBuilder().path(id.toString()).build()).entity(feature).build();
}
}
you can implement ContainerResponseFilter and customise the response based on your requirement.
ex:
#Provider
public class LoggingResponseFilter
implements ContainerResponseFilter {
private static final Logger logger = LoggerFactory.getLogger(LoggingResponseFilter.class);
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) throws IOException {
String method = requestContext.getMethod();
logger.debug("Requesting " + method + " for path " + requestContext.getUriInfo().getPath());
Object entity = responseContext.getEntity();
if (entity != null) {
logger.debug("Response " + new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(entity));
}
}
}
Customize the above code and implement your business logic.
You can use Request or Response filters depends on what you want to check for null.
check the docs here
This took me quite a while to work out so I wanted to share it. Most information came from SO and I wanted to consolidate into this one place.
My requirements are to upload files using a RESTFul POST. Due to possibly large files I wanted to stream the files. I obviously want to be able to read the response.
I planned to use Jersey as the REST Server and Spring's RestTemplate as the client (and for testing).
The problem I faced was streaming POSTs and receiving a response. How can I do that? (Rhetorical question - I answer this!)
It's unnecessary to go through all these hoops with a RequestCallback. Simply use a PathResource.
PathResource pathResource = new PathResource(theTestFilePath);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(pathResource), String.class);
Spring will use a ResourceHttpMessageConverter to serialize the file identified by the given Path to the request body. Internally, the Spring 4.x implementation uses a buffer size of 4096 bytes (which is also what IOUtils#copy(..) uses).
Obviously, you can provide the response type you want. The example above expects the response body as a String. With a ResponseEntity, you can access all the response headers with
HttpHeaders responseHeaders = response.getHeaders();
I am using SpringBoot 1.2.4.RELEASE with Jersey being pulled in by:
compile("org.springframework.boot:spring-boot-starter-jersey")
I created the project with the brilliant Spring Starter Project (Spring Tool Suite > New or you can do through a website I believe and no doubt IntelliJ has this capability also). And chose 'Jersey (JAX-RS)' option. In the gradle build.gradle I also added the dependency:
compile('commons-io:commons-io:2.4')
I wrote this server side code.
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import javax.ws.rs.Consumes;
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;
import javax.ws.rs.core.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
import org.me.fileStore.service.FileStoreService;
#RestController
#Path("/filestore")
public class FileStoreRestService {
private static Logger logger = LoggerFactory.getLogger(FileStoreRestService.class);
#Autowired
private FileStoreService fileStoreService;
#POST
#Path("upload")
#Consumes(MediaType.APPLICATION_OCTET_STREAM)
#Produces(MediaType.APPLICATION_JSON)
public Response Upload(InputStream stream) throws IOException, URISyntaxException { //
String location = fileStoreService.upload(stream); // relative path
URI loc = new URI(location);
Response response = Response.created(loc).build();
System.out.println("POST - response: " + response + ", :" + response.getHeaders());
return response;
}
Where i had most troubles was in getting a Response with a location.
Firstly I had to handle streaming large files. I followed https://stackoverflow.com/a/15785322/1019307 as you can see in the test below. I was NOT obtaining a Response no matter what I tried with the HttpMessageConverterExtractor as per that post:
final HttpMessageConverterExtractor<String> responseExtractor =
new HttpMessageConverterExtractor<String>(String.class, restTemplate.getMessageConverters());
After finding https://stackoverflow.com/a/6006147/1019307 I wrote:
private static class ResponseFromHeadersExtractor implements ResponseExtractor<ClientHttpResponse> {
#Override
public ClientHttpResponse extractData(ClientHttpResponse response) {
System.out.println("StringFromHeadersExtractor - response headers: " + response.getHeaders());
return response;
}
}
This gave me this test:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.TestRestTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestTemplate;
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = FileStoreApplication.class)
#WebAppConfiguration
#IntegrationTest("server.port:9000")
public class FileStoreRestServiceTest {
private static Logger logger = LoggerFactory.getLogger(FileStoreRestServiceTest.class);
protected final Log logger2 = LogFactory.getLog(getClass());
String base = "http://localhost:9000/filestore";
private RestTemplate restTemplate = new TestRestTemplate();
#Test
public void testMyMethodExecute() throws IOException {
String content = "This is file contents\nWith another line.\n";
Path theTestFilePath = TestingUtils.getTempPath(content);
InputStream inputStream = Files.newInputStream(theTestFilePath);
String url = base + "/upload";
final RequestCallback requestCallback = new RequestCallback() {
#Override
public void doWithRequest(final ClientHttpRequest request) throws IOException {
request.getHeaders().setContentType(MediaType.APPLICATION_OCTET_STREAM);
IOUtils.copy(inputStream, request.getBody());
}
};
final RestTemplate restTemplate = new RestTemplate();
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setBufferRequestBody(false);
restTemplate.setRequestFactory(requestFactory);
ClientHttpResponse response = restTemplate.execute(url, HttpMethod.POST, requestCallback,
new ResponseFromHeadersExtractor());
URI location = response.getHeaders().getLocation();
System.out.println("Location: " + location);
Assert.assertNotNull(location);
Assert.assertNotEquals(0, location.getPath().length());
}
private static class ResponseFromHeadersExtractor implements ResponseExtractor<ClientHttpResponse> {
#Override
public ClientHttpResponse extractData(ClientHttpResponse response) {
System.out.println("StringFromHeadersExtractor - response headers: " + response.getHeaders());
return response;
}
}
I need to refactor much in that test out into some services.
I am having trouble using an #Service annotated JAX-RS resource from within a delegate class. Here is my setup:
MyServlet.java
package com.company.mobileservice.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.HttpRequestHandler;
public class MyServlet implements HttpRequestHandler {
#Autowired
MyDelagate delegate;
private void writeResponse(HttpServletRequest request,
HttpServletResponse response, String delegateResponse) {
try {
response.setContentType("application/json");
String callback = request.getParameter("callback");
if (callback != null) {
delegateResponse = callback + "(" + delegateResponse + ");";
} else {
throw new Exception("Callback was null.");
}
response.getWriter().write(delegateResponse);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private String delegateGetRequest(HttpServletRequest request) {
return delegate.handleRequest(request);
}
#Override
public void handleRequest(HttpServletRequest request,
HttpServletResponse response) {
String delegateResponse = delegateGetRequest(request);
writeResponse(request, response, delegateResponse);
}
}
MyDelegate.java
package com.company.mobileservice.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.Authentication;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import com.company.mobileservice.cards.CardResource;
#Component
public class MyDelagate {
#Autowired
private CardResource cardResource;
public String handleRequest(HttpServletRequest request) {
return addCard(request);
}
// Proxies the request to CardResource
private String addCard(HttpServletRequest request) {
String accountID = request.getParameter("accountID");
Card card = new Card();
card.setPan(accountInformation.getAccountNumber().toString());
card.setPaymentTypeId("ABCD1234");
Response response = cardResource.addCard(request, "TEST", null, card);
return response.toString();
}
}
CardResource.java
package com.company.mobileservice.cards;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import com.company.mobileservice.model.Card;
#Path("/{appId}/cards")
#Service
#Scope("singleton")
public class CardResource {
#POST
#Consumes({"application/xml", "application/json"})
#Produces({"application/xml", "application/json"})
public Response addCard(
#Context HttpServletRequest request,
#PathParam("appId") String appId,
#QueryParam("location") String location,
Card card) {
// Do work here
}
}
What I want to do, is call my #Service from within the delegate. I was able to successfully inject the CardResource in to my delegate from the application context, but I was wondering if there is another way to access this service by using the RESTful #Path method.
After some more searching, I've determined that this isn't possible. I was hoping for some kind of service directory that I could to get the appropriate service from. In the end, I decided to just make a call to the service at localhost. It essentially does the job, but it sure would be nice if I could make REST service calls from within my own application without having to configure a client.