JAX-RS inject the value of URI parameter - java

I am trying to get the user by id with the following method:
#Path("/v1/user/")
public class UserRestService extends BaseRestWebService {
#GET
#Path("/customers/{id}")
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Catalog getCustomerById(#Context HttpServletRequest httpServletRequest, #PathParam("id") String userId){
IlsCustomer customer = getUserService().getUserById(IlsCustomer.class, Long.parseLong(userId));
Catalog catalog = new Catalog();
catalog.add(customer);
return catalog;
}
}
I am using Postman and in postman when I type: https://localhost:8181/iPCP/restServices/v1/user/customers/6560
I am getting error :
The page cannot be found (404)
You tried to access a page that does not exist. Please check the entered URL.
But if I type URL: https://localhost:8181/iPCP/restServices/v1/user/customers
the response is: {}

Related

Spring http request validation with anotations

I am trying to implement validation of incoming http request in spring boot app.
I was following these instructions:
https://www.yawintutor.com/how-to-validate-request-body-in-spring-boot/
but I don't get response like stated in article.
I am getting exception in my console though: DefaultHandlerExceptionResolver: ... DefaultMessageSourceResolvable: default message [must be a well-formed email address]]
Process is stopped based on set constraint (email formating, obviously), but I don't get http response messages, just Bad Request.
This is my controller:
#RestController
#Validated
#RequestMapping(path = "/user", produces = MediaType.APPLICATION_JSON_VALUE)
public class UserController {
#PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<User> createUser(#Valid #RequestBody User user) {
User createdUser = userService.createUser(user);
return ResponseEntity.ok(user);
}
}
And this is entity :
#Entity
#Builder
#Data
#NoArgsConstructor
#AllArgsConstructor
public class User {
#Email
private String email;
}
What am I missing?
First of all I'd like to mention that for me the provided link (https://www.yawintutor.com/how-to-validate-request-body-in-spring-boot/) didn't work somehow...
Now to your question. As I see it, in order to archive this you'd have to create a validator first and then you could continue with something line this (not your example but it should help):
#RequestMapping(value = "/validation", method = RequestMethod.POST)
public ResponseEntity<?> acceptData(#Valid #RequestBody Data data, Errors errors,
#RequestHeader(HttpHeaders.ACCEPT_LANGUAGE) String language) {
stringValueValidator.validate(language, data, errors);
if (errors.hasErrors()) {
return new ResponseEntity<>(createErrorString(errors), HttpStatus.BAD_REQUEST);
}
return new ResponseEntity<>(HttpStatus.OK);
}
Use #ControllerAdvice and create your own response Object for representing not valid arguments. Example below will return all not valid arguments with its messages.
#ControllerAdvice
public class ExceptionHandlerClass extends ResponseEntityExceptionHandler {
#Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
List<String> validationList = ex.getBindingResult().getFieldErrors().stream().map(fieldError->fieldError.getDefaultMessage()).collect(Collectors.toList());
return new ResponseEntity<>(new ExceptionObject(false,validationList), status);
} }

JAXB post api does not accept json request with generic 500 error in java

I have to accept and return json using post api :
my api looks like this:
#Path("path/v1")
#Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
#Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public class ServiceCommonImpl implements ServiceCommon {
private static Logger logger = Logger.getLogger(ServiceCommonImpl.class);
private Authorizor authorizor;
private Validator validator;
private ServiceCommonBO ServiceCommonBO;
private Map<String, String> envMap;
#POST
#Path("details")
#Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Response getAcquirerIdCDetailsPOST(CRequestType Id,
#QueryParam("Format") String format,
#HeaderParam("clientid") String userId) {
return getCDetails(Id,format, userId);
}
This api accepts XML request but not json, when json is given then it throws generic 500 message with no details
Any help would be appreciated, please let me know if you need more info.

Java: PUT request without id getting submitted as POST

I have create and update api calls for same entities. If user send a PUT request with no object id, controller accepts it as a POST request and creates a new object. How can I prevent that?
#POST
#Consumes({MediaType.APPLICATION_XML})
#Produces({MediaType.APPLICATION_XML})
public Response create(Entity entity){}
#PUT
#Path("/{id}")
#Consumes({ MediaType.APPLICATION_XML })
#Produces({ MediaType.APPLICATION_XML })
public Response update(#PathParam("id") int id,Entity entity){}
Is there a way to make request parameter required for update? That may resolve the issue as well.
Add a RegEx pattern from your #Path.
Syntax:
#Path("/{" variable-name [ ":" regular-expression ] "}")
Example:
#Path("/{id: <replace_with_reg_exp>}")

How I return HTTP 404 JSON/XML response in JAX-RS (Jersey) on Tomcat?

I have the following code:
#Path("/users/{id}")
public class UserResource {
#Autowired
private UserDao userDao;
#GET
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public User getUser(#PathParam("id") int id) {
User user = userDao.getUserById(id);
if (user == null) {
throw new NotFoundException();
}
return user;
}
If I request for a user that doesn't exists, like /users/1234, with "Accept: application/json", this code returns an HTTP 404 response like one would expect, but returns Content-Type sets to text/html and a body message of html. Annotation #Produces is ignored.
Is it a problem of code or a problem of configuration?
Your #Produces annotation is ignored because uncaught exceptions are processed by the jax-rs runtime using a predefined (default) ExceptionMapper If you want to customize the returned message in case of a specific exception you can create your own ExceptionMapper to handle it. In your case you need one to handle the NotFoundException exception and query the "accept" header for the requested type of the response:
#Provider
public class NotFoundExceptionHandler implements ExceptionMapper<NotFoundException>{
#Context
private HttpHeaders headers;
public Response toResponse(NotFoundException ex){
return Response.status(404).entity(yourMessage).type( getAcceptType()).build();
}
private String getAcceptType(){
List<MediaType> accepts = headers.getAcceptableMediaTypes();
if (accepts!=null && accepts.size() > 0) {
//choose one
}else {
//return a default one like Application/json
}
}
}
You can use the Response return. Example below:
#GET
#Path("{id}")
#Produces(MediaType.APPLICATION_JSON)
public Response get(#PathParam("id") Long id) {
ExampleEntity exampleEntity = getExampleEntityById(id);
if (exampleEntity != null) {
return Response.ok(exampleEntity).build();
}
return Response.status(Status.NOT_FOUND).build();
}
that 404 is returned by your server as it is expected that you will pass things in following form
/users/{id}
but you are passing it as
/users/user/{id}
which resource is not existing at all
try accessing resource as /users/1234
EDIT:
create a class like
class RestResponse<T>{
private String status;
private String message;
private List<T> objectList;
//gettrs and setters
}
now in case you want response for User you can create it as following
RestResponse<User> resp = new RestResponse<User>();
resp.setStatus("400");
resp.setMessage("User does not exist");
and signature of your rest method would be like following
public RestResponse<User> getUser(#PathParam("id") int id)
while in case successful response you can set things like
RestResponse<User> resp = new RestResponse<User>();
List<User> userList = new ArrayList<User>();
userList.add(user);//the user object you want to return
resp.setStatus("200");
resp.setMessage("User exist");
resp.setObjectList(userList);

Receiving JSON Response

I am trying to receive a JSON response with Jersey but it is always sending null. Here is my service code:
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML,
MediaType.TEXT_XML })
#Path("/songs/")
public Room AddSong(#PathParam("json") String Info) {
Song newSong = new newSong();
newSong.addSong(Info);
return newSong;
}
In this case, "Info" is always null. I receive a 200 response from the server so I know the JSON is being sent. The only other thing im not sure is, should I sent JSON in UTF-8?
First of all, you need to use #PathParam correctly. You need to specify {json} in your url. Look at the example
UPD: It's just occurred to me, you in your case you don't need to use #PathParam at all. Just put it away and it should work.
Path parameters take the incoming URL and match parts of the path as a parameter. By including {name} in a #Path annotation, the resource
can later access the matching part of the URI to a path parameter with
the corresponding "name". Path parameters make parts of the request
URL as parameters which can be useful in embedding request parameter
information to a simple URL.
#Path("/books/{bookid}")
public class BookResource {
#GET
public Response invokeWithBookId(#PathParam("bookid") String bookId) {
/* get the info for bookId */
return Response.ok(/* some entity here */).build();
}
#GET
#Path("{language}")
public Response invokeWithBookIdAndLanguage(#PathParam("bookid") String bookId, #PathParam("language") String language) {
/* get the info for bookId */
return Response.ok(/* some entity here */).build();
}
}
In your rest code argument Info takes value from #Path("/songs/{json}") but you have specify #Path("/songs/") so json will always be null
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML,
MediaType.TEXT_XML })
#Path("/songs/")
public Room AddSong(#PathParam("json") String Info) {
Song newSong = new newSong();
newSong.addSong(Info);
return newSong;
}
You do like this and then everything will be fine :
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML,
MediaType.TEXT_XML })
#Path("/songs/{json}")
public Room AddSong(#PathParam("json") String Info) {
Song newSong = new newSong();
newSong.addSong(Info);
return newSong;
}
For more info refer JAX-RS Parameters
You do not need the #PathParam as the JSON contents should be in the POST body. You have declared the return type to be Room, but are you not trying to return type Song? Assuming this is a simple JSON wrapped string, the contents are in the POST body, and you want Song returned in the 200 OK then you can try this:
#POST
Consumes(MediaType.APPLICATION_JSON)
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML })
#Path("/songs/")
public Song AddSong(String Info) {
Song newSong = new newSong();
newSong.addSong(Info);
return newSong;
}
Optionally, if you want to use a JSON representation of Song in the API, you can replace String Info with Song newSong and then specific Song in the POST body.

Categories

Resources