Pattern.List validation regexp fails - java

Got myself stuck in following problem: previously I had a single regexp to check MSISDN and it looked like this: (380)[0-9]{9}. It worked like a charm but change request came in and I had to split it into two parts - first to check if the string start with 380 and the second one to check if it contains only digits and contains 12 characters. For some reason it doesn't work and fails during test on totally valid MSISDN: 380671112233. I've tried googling thing like regexp which check strating characters ^ but all my experiments failed. Can anybody suggest what am I doing wrong ? Thanks in advance!
#Slf4j
#Validated
#RestController
#RequiredArgsConstructor
#RequestMapping(InfoController.INFO_ENDPOINT )
public class InfoController {
public static final String INFO_ENDPOINT = "/info";
private final InfoService service;
#GetMapping(value = "/{msisdn}")
#ResponseBody
public InfoResponse getInfo(
#Pattern.List({
#Pattern(regexp = "(380)", message = "MSISDN_INCORRECT"),
#Pattern(regexp = "[0-9]{12}", message = "MSISDN_OUT_OF_RANGE")
})
#PathVariable("msisdn") String msisdn,
#RequestParam("cid") String cid) {
log.info("[{}] get information for msisdn {}", cid, msisdn);
InfoResponse response = service.getInfo(msisdn, cid);
log.info("[{}] successful response for msisdn {} - {}", cid, msisdn, response);
return response;
}
}
My test setup
private static final String CID = "123-aaa-bbb-312";
public static final String MSISDN = "380671122333";
public static final String NAME = "PP AA";
public static final long ID = 476561L;
public static final int DISTANCE = 69;
#Autowired
private MockMvc mockMvc;
#MockBean
private InfoService service;
#Test
#DisplayName("Valid request. Expected: valid response")
public void testController1() throws Exception {
InfoResponse response = new InfoResponse(MSISDN, NAME, ID, DISTANCE);
when(service.getInfo(any(), any())).thenReturn(response);
String request = UriComponentsBuilder
.fromPath(InfoController.INFO_ENDPOINT)
.pathSegment(MSISDN)
.queryParam("cid", CID)
.build().toString();
mockMvc.perform(get(request))
.andDo(print())
.andExpect(content().json(
"{\"param1\":\"" + MSISDN + "\"" +
",\"param2\":\"" + NAME + "\"" +
",\"param3\":" + ID +
",\"param4\":" + DISTANCE + "}"
))
.andExpect(status().isOk());
}

Related

WebClientRequestException when wiremocking Spring Boot Service POST method

I'm testing my Service in Spring Boot, but I'm getting WebClientRequestException: failed to resolve 'null' after 6 queries; nested exception is java.net.UnknownHostException: failed to resolve 'null' after 6 queries.
I'm new to mocking and testing in general. I guess stubbing is properly done, but asserting is done wrong. Here's my service:
public String changeState(String ids) {
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
form.add("ids", ids);
return webClient.post()
.uri("/vobjects/ecotox_study__c/actions/Objectlifecyclestateuseraction.ecotox_study__c.study_setup_completed_state__c.change_state_to_study_contracted_useract__c")
.header(HttpHeaders.AUTHORIZATION, getSessionId())
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.bodyValue(form)
.retrieve()
.bodyToMono(String.class)
.block();
}
And here's my test, with the response from Postman as a body:
#Test
#DisplayName("Test changeState")
void changeState() {
String body = "{\n" +
" \"responseStatus\": \"SUCCESS\",\n" +
" \"data\": [\n" +
" {\n" +
" \"responseStatus\": \"SUCCESS\",\n" +
" \"id\": \"V4600000001K001\",\n" +
" }\n" +
" ]\n" +
"}";
wireMockServer.stubFor(post(urlEqualTo("/api/v21.3/vobjects/ecotox_study__c/actions/Objectlifecyclestateuseraction.ecotox_study__c.study_setup_completed_state__c.change_state_to_study_contracted_useract__c"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody(body))
);
String vaultIds = vaultServiceTest.changeState("V4600000001K001");
assertEquals(body, vaultIds);
}
As I can see, asserting is obviously done wrong, because I'm asserting the whole body vs. just a single string. I'm not sure is this the right approach or my test method is wrong as a whole.
WebClientRequestException: failed to resolve 'null' after 6 queries;
This error message suggests that the WebClient is being created with a null base URL when the test is run. Not sure how the WebClient is being created in the actual code, but one approach that could also make this work in the test would be to create one in the test class with localhost as the base URL so that it will work with WireMock.
For example:
#Test
#DisplayName("Test changeState")
void changeState() {
//Create and start the WireMockServer for localhost on port 8090
WireMockServer wireMockServer = new WireMockServer(8090);
wireMockServer.start();
//Create a WebClient with base URL localhost on port 8090
WebClient localhostWebClient = WebClient.builder().baseUrl("http://localhost:8090").build();
//Initialize VaultService with the localhost web client
VaultService vaultService = new VaultService(localhostWebClient);
...
To allow the WebClient to be injected into the Vault service, add a parameter for WebClient in the constructor:
public class VaultService {
private WebClient webClient;
public VaultService(WebClient webClient) {
this.webClient = webClient;
}
...
As I can see, asserting is obviously done wrong, because I'm asserting the whole body vs. just a single string.
The JSON response can be mapped to a Java object assuming the field names and data types match up, and the JSON is syntactically valid. Here is some Java objects that could be made that matches the data model of the JSON response:
VaultResponse.java:
public class VaultResponse {
private String responseStatus;
private VaultResponseData[] data;
public String getResponseStatus() {
return responseStatus;
}
public void setResponseStatus(String responseStatus) {
this.responseStatus = responseStatus;
}
public VaultResponseData[] getData() {
return data;
}
public void setData(VaultResponseData[] data) {
this.data = data;
}
}
VaultResponseData.java:
public class VaultResponseData {
private String responseStatus;
private String id;
public String getResponseStatus() {
return responseStatus;
}
public void setResponseStatus(String responseStatus) {
this.responseStatus = responseStatus;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Now in the changeState() method, the response can be mapped to a VaultResponse object instead of a String:
return webClient.post()
.uri("/vobjects/ecotox_study__c/actions/Objectlifecyclestateuseraction.ecotox_study__c.study_setup_completed_state__c.change_state_to_study_contracted_useract__c")
.header(HttpHeaders.AUTHORIZATION, getSessionId())
.header(HttpHeaders.ACCEPT, PageAttributes.MediaType.APPLICATION_JSON_VALUE)
.bodyValue(form)
.retrieve()
.bodyToMono(VaultResponse.class) //Response can be mapped to an Object instead of a raw String
.block();
And finally, in the assert, you can assert on just the ID string instead of the whole JSON response body. A couple of things have to be fixed as well:
There is an extra comma after the ID in the JSON body. \"id\": \"V4600000001K001\",\n" should become \"id\": \"V4600000001K001\"\n"
The WireMock URL should match the URL being used in the code.
Here is the whole test method after all of the changes:
#Test
#DisplayName("Test changeState")
void changeState() {
//Create and start the WireMockServer for localhost on port 8090
WireMockServer wireMockServer = new WireMockServer(8090);
wireMockServer.start();
//Create a WebClient with base URL localhost on port 8090
WebClient localhostWebClient = WebClient.builder().baseUrl("http://localhost:8090").build();
//Initialize VaultService with the localhost web client
VaultService vaultService = new VaultService(localhostWebClient);
String body = "{\n" +
" \"responseStatus\": \"SUCCESS\",\n" +
" \"data\": [\n" +
" {\n" +
" \"responseStatus\": \"SUCCESS\",\n" +
" \"id\": \"V4600000001K001\"\n" + //Extra comma here was removed to make this valid JSON
" }\n" +
" ]\n" +
"}";
//This URL must match the URL being called in the code
wireMockServer.stubFor(post(urlEqualTo("/vobjects/ecotox_study__c/actions/Objectlifecyclestateuseraction.ecotox_study__c.study_setup_completed_state__c.change_state_to_study_contracted_useract__c"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody(body))
);
VaultResponse vaultResponse = vaultService.changeState("V4600000001K001");
assertEquals("V4600000001K001", vaultResponse.getData()[0].getId());
}

Getting Bad Request while trying to consume REST API in Java SpringBoot

Hi I am trying to consume a REST endpoint using POST, but I am getting the error below. The endpoint gives proper response in POSTMAN, but I am getting error in Java. Please let me know where the mistake is.
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException$BadRequest: 400 Bad Request: [{
"error":"unsupported_grant_type",
"error_description":"The given grant_type is not supported"
}]] with root cause
org.springframework.web.client.HttpClientErrorException$BadRequest: 400 Bad Request: [{
"error":"unsupported_grant_type",
"error_description":"The given grant_type is not supported"
}]
Below is code:
Controller:
public class MemberController {
private static final Logger log = LoggerFactory.getLogger(MemberController.class);
#Autowired
MemberService memberService;
#PostMapping(value = "/token", headers = "Accept=application/json")
public String getToken() {
log.info("Test getToken method");
return memberService.callTokenService();
}
Service Class:
public class MemberService {
private static final Logger log = LoggerFactory.getLogger(MemberService.class);
private RestTemplate restTemplate = new RestTemplate();
final String tokenURL = "-------";
public String callTokenService() {
log.info("Inside Service");
TokenInput input = new TokenInput();
String clientId = "l7xxef159fc30ee8479e9a7dab859c458a4d";
String clientSecret = "a63d0b4a01b844c0b7e7eb724ef13959";
String grantType = "client_credentials";
input.setCLIENT_ID(clientId);
input.setCLIENT_SECRET(clientSecret);
input.setGRANT_TYPE(grantType);
ResponseEntity<TokenProperties> response = restTemplate.postForEntity(tokenURL, input, TokenProperties.class);
HttpStatus status = response.getStatusCode();
log.info("Status: "+status);
log.info("Response: "+response.toString());
return response.toString();
}
}
POJO class:
#JsonIgnoreProperties(ignoreUnknown = true)
public class TokenProperties {
String access_token;
String token_type;
String expires_in;
String scope;
public String getAccess_token()
{
return access_token;
}
public void setAccess_token(String access_token)
{
this.access_token = access_token;
}
public String getToken_type()
{
return token_type;
}
public void setToken_type(String token_type)
{
this.token_type = token_type;
}
public String getExpires_in()
{
return expires_in;
}
public void setExpires_in(String expires_in)
{
this.expires_in = expires_in;
}
public String getScope()
{
return scope;
}
public void setScope(String scope)
{
this.scope = scope;
}
#Override
public String toString() {
return "{" + "access_token='" + access_token + '\'' + ", token_type=" + token_type + ", expires_in=" + expires_in + '\'' + "scope='" + scope + '}';
}
}
TokenInput POJO:
package com.memberservice_v2;
public class TokenInput {
String CLIENT_ID;
String CLIENT_SECRET;
String GRANT_TYPE;
public String getCLIENT_ID() {
return CLIENT_ID;
}
public void setCLIENT_ID(String cLIENT_ID) {
CLIENT_ID = cLIENT_ID;
}
public String getCLIENT_SECRET() {
return CLIENT_SECRET;
}
public void setCLIENT_SECRET(String cLIENT_SECRET) {
CLIENT_SECRET = cLIENT_SECRET;
}
public String getGRANT_TYPE() {
return GRANT_TYPE;
}
public void setGRANT_TYPE(String gRANT_TYPE) {
GRANT_TYPE = gRANT_TYPE;
}
}
Can anyone please help me out? Please let me know where the mistake is. Thanks in Advance!
Your request ResponseEntity<TokenProperties> response = restTemplate.postForEntity(tokenURL, null, TokenProperties.class); to token endpoint is incomplete. You're not passing the payload (token request) as far as I can see in the aforementioned code.
First, create the token request and set the appropriate attributes such as client id, grant type etc.
TokenRequest tokenRequest = new TokenRequest();
// set the attributes as per the token endpoint
ResponseEntity<TokenProperties> response = restTemplate.postForEntity(tokenURL, tokenRequest, TokenProperties.class);

How to test getting parameters on the Rest service using the Post method

I'm trying to test getting parameters for processing a request using the Post method
#RestController
#RequestMapping("api")
public class InnerRestController {
…
#PostMapping("createList")
public ItemListId createList(#RequestParam String strListId,
#RequestParam String strDate) {
…
return null;
}
}
test method
variant 1
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class InnerRestControllerTest {
#LocalServerPort
private int port;
#Autowired
private TestRestTemplate restTemplate;
#Test
void innerCreatePublishList() {
String url = "http://localhost:" + this.port;
String uri = "/api/createList";
String listStr = "kl";
String strDate = "10:21";
URI uriToEndpoint = UriComponentsBuilder
.fromHttpUrl(url)
.path(uri)
.queryParam("strListId", listStr)
.queryParam("strDate ", strDate)
.build()
.encode()
.toUri();
ResponseEntity< ItemListId > listIdResponseEntity =
restTemplate.postForEntity(uri, uriToEndpoint, ItemListId.class);
}
}
variant 2
#Test
void createList() {
String uri = "/api/createList";
String listStr = "kl";
String strDate = "10:21";
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(uri)
.queryParam("strListId", listStr)
.queryParam("strDate ", strDate);
Map<String, String> map = new HashMap<>();
map.put("strListId", listStr);//request parameters
map.put("strDate", strDate);
ResponseEntity< ItemListId > listIdResponseEntity =
restTemplate.postForEntity(uri, map, ItemListId.class);
}
Update_1
In my project exceptions is handled thus:
dto
public final class ErrorResponseDto {
private String errorMsg;
private int status;
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss")
LocalDateTime timestamp;
...
handler
#RestControllerAdvice
public class ExceptionAdviceHandler {
#ExceptionHandler(value = PublishListException.class)
public ResponseEntity<ErrorResponseDto> handleGenericPublishListDublicateException(PublishListException e) {
ErrorResponseDto error = new ErrorResponseDto(e.getMessage());
error.setTimestamp(LocalDateTime.now());
error.setStatus((HttpStatus.CONFLICT.value()));
return new ResponseEntity<>(error, HttpStatus.CONFLICT);
}
}
In methods, where necessary, I throw a specific exception...
.w.s.m.s.DefaultHandlerExceptionResolver : Resolved
[org.springframework.web.bind.MissingServletRequestParameterException:
Required String parameter 'strListId' is not present]
Who knows what the error is. Please explain what you need to add here and why ?
Let's take a look on declarations of postEntity:
postForEntity(URI url, Object request, Class<T> responseType)
...
postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables)
As you can see, first argument is either URI or String with uriVariables, but second argument is always request entity.
In you first variant you put uri String as URI and then pass uriToEndpoint as request entity, pretending that it is request object. Correct solution will be:
ResponseEntity<ItemListId> listIdResponseEntity =
restTemplate.postForEntity(uriToEndpoint, null, ItemListId.class);
Addressing your comments.
If server responded with HTTP 409, RestTemplate will throw exception with content of your ErrorResponseDto. You can catch RestClientResponseException and deserialize server response stored in exception. Something like this:
try {
ResponseEntity<ItemListId> listIdResponseEntity =
restTemplate.postForEntity(uriToEndpoint, null,
ItemListId.class);
...
} catch(RestClientResponseException e) {
byte[] errorResponseDtoByteArray = e.getResponseBodyAsByteArray();
// Deserialize byte[] array using Jackson
}

Java / Jackson - 'Unrecognized token' passing JSON object parameter

Java JAX-RS web service with Jersey / Jackson, a service method expects a User parameter (POJO) as JSON. The client app (Angular 6) sends a POST request containing the User parameter (serialized as JSON). The service method call fails with error message: "Unrecognized token 'jsonUser': was expecting ('true', 'false' or 'null')".
Here is the User class (POJO) - you can see I tried annotating all the properties with #JsonProperty, but it's unnecessary, as I'm not "renaming" them:
import java.io.Serializable;
import javax.ws.rs.FormParam;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
//import org.glassfish.jersey.media.multipart.FormDataParam;
/**
* JavaBean for passing the User properties between the UI app (Angular)
* and TearsWs. Implementation requires this to be serializable (JSON).
*/
#JsonIgnoreProperties({ "DELIM" })
public class User implements Serializable {
private String userName;
private String employeeId;
private String employeeName;
private String homeUnitCode;
private boolean certifier;
private HomeUnit[] tkHomeUnits;
private boolean supervisor;
private Employee[] whoISupervise;
private boolean hrStaff;
private boolean collector;
private final static String DELIM = ", ";
public User() {
}
// getters / setters
//#JsonProperty("userName")
public void setUserName(String ldapUid) {
this.userName = ldapUid;
}
public String getUserName() {
return this.userName;
}
//#JsonProperty("employeeId")
public void setEmployeeId(String employeeId) {
this.employeeId = employeeId;
}
public String getEmployeeId() {
return this.employeeId;
}
//#JsonProperty("employeeName")
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
public String getEmployeeName() {
return this.employeeName;
}
//#JsonProperty("homeUnitCode")
public void setHomeUnitCode(String homeUnitCode) {
this.homeUnitCode = homeUnitCode;
}
public String getHomeUnitCode() {
return this.homeUnitCode;
}
//#JsonProperty("certifier")
public void setCertifier(boolean certifier) {
this.certifier = certifier;
}
public boolean getCertifier() {
return this.certifier;
}
//#JsonProperty("tkHomeUnits")
public void setTkHomeUnits(HomeUnit[] tkHomeUnitCodes) {
this.tkHomeUnits = tkHomeUnitCodes;
}
public HomeUnit[] getTkHomeUnits() {
return this.tkHomeUnits;
}
//#JsonProperty("supervisor")
public void setSupervisor(boolean supervisor) {
this.supervisor = supervisor;
}
public boolean isSupervisor() {
return this.supervisor;
}
//#JsonProperty("whoISupervise")
public void setWhoISupervise(Employee[] whoISupervise) {
this.whoISupervise = whoISupervise;
}
public Employee[] getWhoISupervise() {
return this.whoISupervise;
}
//#JsonProperty("hrStaff")
public void setHrStaff(boolean hrStaff) {
this.hrStaff = hrStaff;
}
public boolean isHrStaff() {
return this.hrStaff;
}
//#JsonProperty("collector")
public void setCollector(boolean collector) {
this.collector = collector;
}
public boolean isCollector() {
return this.collector;
}
//methods
public boolean hasTauthority() {
return this.certifier || this.collector;
}
public String toString() {
int tkHUs = (tkHomeUnits == null) ? 0 : tkHomeUnits.length;
return "[User: "
+ "userName=" + this.userName + DELIM
+ "employeeId=" + this.employeeId + DELIM
+ "employeeName=" + this.employeeName + DELIM
+ "homeUnitCode=" + this.homeUnitCode + DELIM
+ "certifier=" + this.certifier + DELIM
+ "hrStaff=" + this.hrStaff + DELIM
+ "collector=" + this.collector + DELIM
+ "I can certify " + tkHUs + " homeUnits" + "]";
}
}
Here is the (Java) service method, which should accept and process the POST request:
/**
* Web service method.
*/
#POST
#Path("getTkHomeUnitEmployees")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response getTkHomeUnitEmployees(User user, #HeaderParam("X-Request-Param") String homeUnitCode) throws Exception {
String exceptionMessage;
if (user == null) {
exceptionMessage = "getTkHomeUnitEmployees() received a null User.";
log.error(exceptionMessage);
Response response = Response
.status(500)
.entity(exceptionMessage)
.build();
return response;
}
if (homeUnitCode == null || homeUnitCode.equals("")) {
exceptionMessage = "getTkHomeUnitEmployees() received a null HomeUnitCode.";
log.error(exceptionMessage);
Response response = Response
.status(500)
.entity(exceptionMessage)
.build();
return response;
}
if (!user.hasTauthority()) {
exceptionMessage = "getTkHomeUnitEmployees() received a request from a non-timekeeper and non-collector.";
log.error(exceptionMessage);
Response response = Response
.status(500)
.entity(exceptionMessage)
.build();
return response;
}
try {
Employee[] tkHomeUnitEmployees = new SecurityDao().getTkHomeUnitEmployees(user.getEmployeeId(), homeUnitCode);
Response response = Response
.ok(tkHomeUnitEmployees)
.header("Access-Control-Allow-Origin", "*")
.build();
return response;
} catch (Exception ex) {
exceptionMessage = "getTkHomeUnitEmployees(): " + ex;
Response response = Response
.status(500)
.entity(exceptionMessage)
.build();
return response;
}
}
The User object (client side, Javascript) is converted to JSON and encapsulated as a parameter in HttpParams; the POST passes it in the body of the request.
Here is the (Angular) client method, which sends the POST request to the web service:
getTkHomeUnitEmployees(user: User, homeUnitCode: string): Observable<Employee[]> {
const headers = new HttpHeaders()
.set('Content-Type', 'application/json')
.set('X-Request-Param', homeUnitCode); // homeUnitCode parameter in HttpHeaders
const httpOptions = {
headers: headers
};
let jsonUser: string = JSON.stringify(user);
const httpParams = new HttpParams()
.set('jsonUser', jsonUser);
let postUrl = this.wsUrl + 'getTkHomeUnitEmployees';
//postUrl += '?homeUnitCode=' + homeUnitCode; // homeUnitCode parameter as QueryParam
let obsArrayEmployees: Observable<Employee[]> = this.httpClient.post<Employee[]>(postUrl, httpParams, httpOptions);
return obsArrayEmployees;
}
...here I'm debugging the client (# browser Dev Tools), with a break in the getTkHomeUnitEmployees() method:
...I've displayed the value of jsonUser in the Console:
...here is the error in the Response:
...and here is the Request Params.
So, it appears the Jackson JsonParser is attempting to read and parse the parameter sent in the request, but the parameter includes "jsonUser=" at the beginning as part of it's value (json to be parsed). This is clearly wrong...
The service method blows up before actually entering / processing code; I can't set a breakpoint within the service method to examine the value of the parameter. It behaves as a "parameter invalid, return to caller" response.
I thought to manually hack the "jsonUser=" out of it (# client side), but it's not there. At the client, "jsonUser=" is not part of the parameter value; I believe it's just the key=value syntax of an http parameter (parameter-name=parameter-value), perhaps it's being prepended when the parameter is encapsulated into the HttpParams object.
Obviously I'm doing something wrong, but I haven't been able to figure it out; I thought this was the correct way to do this, but apparently not. Hope someone can help soon, I've been stuck on this for a couple days already.
You don't need to covert the 'user' object to string to pass to backend. Try passing the user object as it is.
this.httpClient.post<Employee[]>(postUrl, user, httpOptions);
And also please check if parameters passed really match the rest service exposed.

Spring MVC: Complex object as parameter

I started to learn spring boot and I'm faced with problems. I have following code:
#RestController
public class UserController {
#RequestMapping("/")
public String getMessageInfo(Message message) {
return "Id is " + message.getId() + ", message is " + message.getMessage() + ", parameter good is " + message.isGood();
}
}
Class Message:
public class Message {
private String message;
private int id;
private boolean good;
public Message() {}
public Message(int id) {this.id = id;}
public Message(String message) {this.message = message;}
public Message(boolean good) {this.good = good;}
public Message(String message, boolean good, int id) {
this.message = message;
this.good = good;
this.id = id;
}
public String getMessage() {
return message;
}
public int getId() {
return id;
}
public boolean isGood() {
return good;
}
}
And when I try to do something like this:
RestTemplate request = new RestTemplate();
String info = request.getForObject("http://localhost:8080/?id=4", String.class);
value of id is ignored. Same problem appears when I send request with boolean good parameter (for example localhost:8080/?good=true). It is called the default constructor instead of Message(boolean)/Message(int). But when I do something like localhost:8080/?message=1234 it isn't ignored. Can you explain me what is the problem?
And one more question: can I send instance of class Message to getMessageInfo in different way than localhost:8080/?message=1234&good=true&id=145? If I have more than 3 parameters? For example if class Message has 100 parameters?
since you are trying to deal with a complex object accept your object from a post request.
#RequestMapping("/",method=RequestMethod.POST)
public String getMessageInfo(#RequestBody Message message) {
return message;
}
in the above code i'm setting method attribute to POST then it will be called when you are making a POST request, and i am using #RequestBody Message message inside the method parameter. which will convert and form an Message object from the incoming request, if you dont put #requestBody annotation then a Bean will be injected to the method by spring instead of forming a one from the request.
you can try this code to make the request
final String uri = "http://localhost:8080/";
Message message = new Message(1, "Adam",true);
RestTemplate restTemplate = new RestTemplate();
Message result = restTemplate.postForObject( uri, message, Message.class);
when making an request create an Message object setting each and every field in it, otherwise you will end up in having Bad request error.
I solved the problem, if add smth like this:
#ModelAttribute("message")
public Message getMessage(String message, boolean good, int id){
return new Message(message, good, id);
}
#RequestMapping("/")
public String getUserInfo(#ModelAttribute("message") Message message) {
return "Id is " + message.getId() + ", message is " + message.getMessage() + ", parameter good is " + message.isGood();
}
all parameters aren't ignored.
You can use like this,
MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
params.add("id", 1);
params.add("good", true);
params.add("message", 1234);
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(params, requestHeaders);
RestTemplate restTemplate = new RestTemplate();
Message message= restTemplate.postForObject("http://localhost:8080/", requestEntity, Message.class);

Categories