I am developing Spring MVC 4 Dynamic web module application.
In my application I have simple CRUD operations.
Get requests are working fine but POST and PUT are not working at all.
I am getting this error:
HTTP Status 400 - The request sent by the client was syntactically incorrect.
This is my controller code for GET:
#RequestMapping(value = "/getCustomreById/{id}", method = RequestMethod.GET)
public ResponseEntity<CustomerDetails> getCustomer(
#PathVariable("id") String id) {
System.out.println(id);
if (id != null)
return new ResponseEntity<CustomerDetails>(
serv.getCustomerById(id), HttpStatus.OK);
else
return new ResponseEntity<CustomerDetails>(
serv.getCustomerById("1"), HttpStatus.OK);
}
and for POST :
#RequestMapping(value = "/addCustomer", method = RequestMethod.POST)
public int AddCustomer(#RequestBody CustomerDetails customer) {
return serv.addCustomer(customer);
}
POST Request :
{
"customerName": "Sid",
"customerEmail": "sid#gmail.com",
"customerAddress": [{
"address1": "123 Street",
"address2": " ",
"zipCode": "400065",
"city": "Mumbai",
"state": "Maharashtra",
"country": "India",
"region": "Gateway of India"
}]
}
I read on stackoverflow on this question that I need to add multipart reosolver but even aafter adding that I am getting same error.
Assuming you just need to send int id as response, add #ResponseBody to the method
#RequestMapping(value = "/addCustomer", method = RequestMethod.POST)
#ResponseBody
public int AddCustomer(#RequestBody CustomerDetails customer) {
return serv.addCustomer(customer);
}
Otherwise return ResponseEntity as you are doing for GET
return new ResponseEntity<Integer>(serv.addCustomer(customer), HttpStatus.OK);
Adding #ResponseBody will work for this question
Related
I have an external API (like this - "https://www.example.com/en/products.json") and once hit the url it gives a json response like this:
{
"product1": {
"title": "Digital Adopter",
"description": "product description",
"image": ""
},
"product2": {
"title": "Router",
"description": "product2 description",
"image": ""
}
}
I want to use RestTemplate to consume above url(https://www.example.com/en/products.json) and tried following code. But didn't get any response or any error. I have less experience in development using Spring Boot RestTemplate and Can someone help me to fix this?
JsontestApplication .java
#SpringBootApplication
public class JsontestApplication {
public static void main(String[] args) {
SpringApplication.run(JsontestApplication.class, args);
}
#Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
Controller Class - Controller1.java
#RestController
public class Controller1 {
#Autowired
RestTemplate restTemplate;
#RequestMapping(value = "/jkl", method = RequestMethod.GET)
public String getProductList() {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity <String> entity = new HttpEntity<String>(headers);
return restTemplate.exchange("https://www.example.com/en/products.json", HttpMethod.GET, entity, String.class).getBody();
}
}
In the application.properties file, I have set the port as server.port=8765 and application is running without any error. This is the url I hit using the Postman - http://localhost:8765/jkl
I'm creating a sample of web service using Spring boot. When I run it in the localhost and test with Postman, it works fine. But when I deploy the application on AWS Lambda, it throws a nullpointerException.
When I was testing locally and on AWS Lambda this was working fine, until I started using #autowired
This is the project structure
The endpont or handle request is in the class LoginController
#Controller
#RequestMapping(value="api/auth/v1")
public class LoginController {
#Autowired
IClientCredentialService _clientCredentialService;
#RequestMapping(value = "/login", method = RequestMethod.POST, headers = "Accept=application/json")
public ResponseEntity<?> login(#RequestBody ClientCredential clientCredential){
//For testing from Postman and AWS, clientCredential is not null.
if(clientCredential == null) {
return new ResponseEntity<VOGenericResponse>(new VOGenericResponse(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.name()), HttpStatus.BAD_REQUEST);
}
if(clientCredential.getClientId() == null || clientCredential.getClientId().equals("")) {
return new ResponseEntity<VOGenericResponse>(new VOGenericResponse(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.name()), HttpStatus.BAD_REQUEST);
}
if(clientCredential.getClientSecret() == null || clientCredential.getClientSecret().equals("")) {
return new ResponseEntity<VOGenericResponse>(new VOGenericResponse(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.name()), HttpStatus.BAD_REQUEST);
}
else {
ClientCredential client = _clientCredentialService.findClientCredential(clientCredential.getClientId(), clientCredential.getClientSecret());
//TODO Obtener token aquí
Token token = new Token();
token.setCode(HttpStatus.OK.value());
token.setDescription(HttpStatus.OK.name());
//Temp
token.setAccessToken("123");
token.setCreatedDate("Hoy");
token.setUpdatedDate("Hoy");
token.setExpiresIn("Mañana");
token.setStartIn("Hoy");
token.setTokenId("321");
token.setTokenType("bearer");
token.setUpdatedDate("hoy");
return new ResponseEntity<Token>(token, HttpStatus.OK);
}
The interface IClientCredentialService, escencially has a method, and the class ClientCredentialServiceImpl, implements that interface:
#Service("clientCredentialService")
#Transactional
public class ClientCredentialServiceImpl implements IClientCredentialService{
#Override
public ClientCredential findClientCredential(String clientId, String clientSecret) {
return new ClientCredential();
}
}
This is the main class:
#SpringBootApplication
public class AwsLambdaSurveyAuthServerLoginV1Application {
public static void main(String[] args) {
SpringApplication.run(AwsLambdaSurveyAuthServerLoginV1Application.class, args);
}
}
And the classes ClientCredential and Token, has a constructor and some getters and setters.
When I run it from postman, It works fine, I get a 200 http response:
{
"code": 200,
"description": "OK",
"tokenId": "321",
"accessToken": "123",
"tokenType": "bearer",
"expiresIn": "Mañana",
"startIn": "Hoy",
"createdDate": "Hoy",
"updatedDate": "hoy"
}
but, when I run It from AWS Lambda y get this error:
{
"errorMessage": "java.lang.NullPointerException",
"errorType": "java.lang.NullPointerException",
"stackTrace": [
"com.gns.survey.authserver.login.controller.LoginController.login(LoginController.java:47)",
"sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
"sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)",
"sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)",
"java.lang.reflect.Method.invoke(Method.java:498)"
]
}
Anyone know what the error is? I really appreciate your help.
/Edit: Method with null validation
Here is my code ,I'm trying to pass the user details as a json input but I'm not able to receive the data in my rest api method. I"m getting all values as null,
this is my json request
{
"userId" : "12345",
"username" : "arun.ammasai",
"createdBy" : "-2",
"updatedBy" : "-2",
"statusCd" : "New",
"createdDate" : "2019-03-03",
"updatedDate" : "2019-03-03"
}
====================================================================
#RequestMapping(value = "/registerUser", method = RequestMethod.POST, consumes = { "application/JSON", "application/XML" })
private String registerUser(User user) {
System.out.println(user.toString());
return "User Created";
}
====================================================================
here is the response in Postman Client
Unexpected 'U'
Update your method signature with #RequestBody annotation. It will automatically deserialize your json into java entity. Be carefull, names in json should be the same as parameters in User object and User object should have getters and setters. So your method should look like
#RequestMapping(value = "/registerUser", method = RequestMethod.POST, consumes = { "application/JSON", "application/XML" })
private String registerUser(#RequestBody User user) {
System.out.println(user.toString()); //What is the reason of doing toString of java Object?
//better to do System.out.println(user.getUsername())
return "User Created";
}
I have a controller with method, which returns PagedResource, which looks like this:
#RequestMapping(value = "search/within", method = RequestMethod.POST)
public #ResponseBody PagedResources within(#RequestBody GeoJsonBody body,
Pageable pageable, PersistentEntityResourceAssembler asm) {
// GET PAGE
return pagedResourcesAssembler.toResource(page, asm);
}
Now, I want to add that method as a link to the root resource, so I do the following:
public RepositoryLinksResource process(RepositoryLinksResource repositoryLinksResource) {
repositoryLinksResource.add(linkTo(methodOn(ShipController.class).within(null, null, null)).withRel("within"));
return repositoryLinksResource;
}
Which works and I get my link, however it add that link without pagination parameters. So it look like this:
"within": {
"href": "http://127.0.0.1:5000/search/within"
},
and I want to turn it into:
"within": {
"href": "http://127.0.0.1:5000/search/within{?page, size}"
},
This previous question on stackoverflow suggests that after fixing the corresponding issue on GitHub it should work by default, however, it doesn't.
What am I doing wrong ?
Automatic Creation of Paginated Links with PagedResourcesAssembler
I had success using PagedResourcesAssembler. Let's say your entity is called
MyEntity. Your within method should return HttpEntity<PagedResources<MyEntity>>.
Your within method should look something similar to the example shown below.
#RequestMapping(value = "search/within", method = RequestMethod.POST)
#ResponseBody
public HttpEntity<PagedResources<MyEntity>>
within(#RequestBody GeoJsonBody body,Pageable pageable,
PagedResourcesAssembler assembler) {
// GET PAGE
Page<MyEntity> page = callToSomeMethod(pageable);
return new ResponseEntity<>(assembler.toResource(page), HttpStatus.OK);
}
Here is a simple example. In this example, the response looked like the one shown below,
{
"_embedded": {
"bookList": [
{
"id": "df3372ef-a0a2-4569-982a-78c708d1f609",
"title": "Tales of Terror",
"author": "Edgar Allan Poe"
}
]
},
"_links": {
"self": {
"href": "http://localhost:8080/books?page=0&size=20"
}
},
"page": {
"size": 20,
"totalElements": 1,
"totalPages": 1,
"number": 0
}
}
Manual Creation of Paginated Self Link
If you're interested in creating the paginated link manually, here's the code snippet you can use,
Page<MyEntity> page = callToSomeMethod(pageable);
ControllerLinkBuilder ctrlBldr =
linkTo(methodOn(ShipController.class).within(body, pageable, asm));
UriComponentsBuilder builder = ctrlBldr.toUriComponentsBuilder();
int pageNumber = page.getPageable().getPageNumber();
int pageSize = page.getPageable().getPageSize();
int maxPageSize = 2000;
builder.replaceQueryParam("page", pageNumber);
builder.replaceQueryParam("size", pageSize <= maxPageSize ?
page.getPageable().getPageSize() : maxPageSize);
Link selfLink =
new Link(new UriTemplate(builder.build().toString()), "self");
In my controller I am having if condition and two different response type. I will get response in JSON format from "if" condition, but I am getting response from else condition like unexpected '0 , instead I need to get my error message'.
My controller code snippet
#RequestMapping(value = "/saveuser", produces = { "application/json" }, consumes = { "application/json" }, method = RequestMethod.POST)
public ResponseEntity<?> addUser(#RequestBody TestUser user)
throws NotFoundException {
System.out.println(user.getAnswer().size());
if(questioncount == user.getAnswer().size())
{
return new ResponseEntity<TestUser>(service.addUser(user),
HttpStatus.OK);
}else {
String one="one";
String erromessage = "Only" + questioncount +" questions are allowed";
System.out.println(erromessage);
return new ResponseEntity<String>(erromessage,HttpStatus.NOT_ACCEPTABLE);
}
}