Issue creating stream definitions via rest interface - spring-xd

I want to make sure I am on the right track with this.
I am getting the following response when attempting to create my stream:
015-11-23T08:59:12-0800 1.3.0.RELEASE ERROR qtp1260026681-23 rest.RestControllerAdvice - Caught exception while handling a request
org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.handleNoMatch(RequestMappingInfoHandlerMapping.java:204) ~[spring-webmvc-4.2.2.RELEASE.jar:4.2.2.RELEASE]
Here is my sample code:
HttpEntity<String> requestEntity;
ResponseEntity<String> responseEntity;
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("name", "testStream");
map.add("definition", "file | log");
map.add("deploy", "true");
requestEntity = new HttpEntity<MultiValueMap>(map, headers);
String url = "http://localhost:9393/streams/definitions"
try
{
responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
body = responseEntity.getBody();
statusCode = responseEntity.getStatusCode();
}
catch (Exception e)
{
String test = e.getMessage();
}
Here is the code that returns the: exception is java.util.regex.PatternSyntaxException: Dangling meta character '*' near index 0
*
^
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
def streamName = "TEST";
def url= "http://localhost:9393/streams/definitions";
String definition = "dod-file-source --dir='zxcv' --dir='([^\s]+(\.(?i)(tar))$)' | transform --script=dod.file.transform.groovy --variables='hotfolderId=1' > queue:StorageStream";
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>()
map.add("name", streamName)
map.add("definition", definition)
map.add("deploy", 'true')
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(map, headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
String body = responseEntity.getBody();
HttpStatus statusCode = responseEntity.getStatusCode();
That is a custom source module dod-file-source but it just adds a few additional features to the file source module

I just ran (a slightly modified version of) your code and had no problems...
HttpEntity<MultiValueMap<String, String>> requestEntity;
ResponseEntity<String> responseEntity;
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("name", "testStream");
map.add("definition", "time | log");
map.add("deploy", "true");
requestEntity = new HttpEntity<MultiValueMap<String, String>>(map, headers);
String url = "http://localhost:9393/streams/definitions";
try
{
responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
String body = responseEntity.getBody();
HttpStatus statusCode = responseEntity.getStatusCode();
}
catch (Exception e)
{
e.printStackTrace();
}
2015-11-23T13:00:44-0500 1.3.0.RELEASE INFO task-scheduler-1 sink.testStream - 2015-11-23 13:00:44
2015-11-23T13:00:45-0500 1.3.0.RELEASE INFO task-scheduler-1 sink.testStream - 2015-11-23 13:00:45
2015-11-23T13:00:46-0500 1.3.0.RELEASE INFO task-scheduler-1 sink.testStream - 2015-11-23 13:00:46
2015-11-23T13:00:47-0500 1.3.0.RELEASE INFO task-scheduler-1 sink.testStream - 2015-11-23 13:00:47

Related

SpringBoot: HttpClientErrorException$BadRequest: 400: [no body] when calling restTemplate.postforEntity or restTemplate.exchange

I am trying to hit a restful endpoint from my springboot application using restTemplate.exchange and restTemplate.postForEntity and I am getting 400 Bad request [no body] exception.
I tried every possible solution to figure out the issue. From the same code I used HttpURLConnection to hit the endpoint and it works fine. I am able to get valid response. I also tried hitting the endpoint from Postman and it works fine
Below is endpoint code
#RestController
#RequestMapping("auth")
#Slf4j
public class AuthController {
#PostMapping(value = "/as/resourceOwner",
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Token> getToken(#RequestParam(required = false)MultiValuedMap<?, ?> params) {
log.info("token endpoint");
return new ResponseEntity<>(new Token(), HttpStatus.OK);
}
}
The below code with HttpURLConnection class works fine
public class Test {
public static void main(String[] args) {
try {
URL url = new URL("http://localhost:8080/fc-services-mock-auth/fmrco/as/resourceOwner");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setDoOutput(true);
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", MediaType.APPLICATION_FORM_URLENCODED_VALUE);
OutputStream writer = urlConnection.getOutputStream();
writer.write("a=a&b=b".getBytes(StandardCharsets.UTF_8));
writer.flush();
writer.close();
BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
System.out.println(e);
}
}
}
But the below code with restTemplate does not work
try {
HttpEntity httpEntity = new HttpEntity<>(createBody(), createHeaders());
ResponseEntity<String> response = restTemplate.exchange(new URI(endpointConfig.getTokenServiceUrl()),
HttpMethod.POST, httpEntity, String.class);
HttpEntity<MultiValueMap<String, String>> request =
new HttpEntity<>(createBody(), createHeaders());
ResponseEntity<TokenResponse> tokenResponse = restTemplate.postForEntity(
new URI(endpointConfig.getTokenServiceUrl()),
request,
TokenResponse.class);
logger.debug(" token process completed");
return tokenResponse.getBody();
} catch (Exception e) {
throw new TokenException(" token error: ", e);
}
private HttpHeaders createHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", MediaType.APPLICATION_FORM_URLENCODED_VALUE);
return headers;
}
private MultiValueMap createBody() {
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("client_id", applicationConfig.getTokenClientId());
map.add("client_secret", applicationConfig.getTokenClientSecret());
map.add("grant_type", "password");
map.add("username", applicationConfig.getTokenUsername());
map.add("password", applicationConfig.getTokenPassword());
return map;
}
Can anyone please tell me what is wrong here?
Additionally I have written another GET restful endpoint like below and while hitting the endpoint using exchange I still get the same error.
#GetMapping(value = "test", produces = MediaType.TEXT_PLAIN_VALUE)
public ResponseEntity<String> test() {
return new ResponseEntity<>("Hello", HttpStatus.OK);
}
try {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.TEXT_PLAIN));
HttpEntity<MultiValueMap<String, String>> entity =
new HttpEntity<>(null, headers);
ResponseEntity<String> response = restTemplate.exchange(
"http://localhost:8080/context/path",
HttpMethod.GET, entity, String.class);
} catch (Exception e) {
System.out.println(e);
}
Also, intentionally I tried making a POST call to the get endpoint to see if it returns 405 Method not allowed. But to my wonder it still returned 400 Bad Request no body.
I finally figured it out. The restTemplate is configured to use a proxy. I removed the proxy and it is working fine now.
You can try something like:-
public void fetchAuthenticationToken() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.setAccept(List.of(MediaType.APPLICATION_JSON));
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("client_id", applicationConfig.getTokenClientId());
map.add("client_secret", applicationConfig.getTokenClientSecret());
map.add("grant_type", "client_credentials");
map.add("username", applicationConfig.getTokenUsername());
map.add("password", applicationConfig.getTokenPassword());
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(map, headers);
String tokenEndPoint = "{your endpoints URL}";
ResponseEntity<TokenResponse> responseEntity = testRestTemplate.exchange(tokenEndPoint,
HttpMethod.POST, entity, TokenResponse.class, new HashMap<String, String>());
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
TokenResponse token = responseEntity.getBody();
assertThat(token).isNotNull();
System.out.println("Auth Token value is "+ token)
}

File Exception while trying to upload file via spock test

I'm getting the below exception while trying to test from a spock test to upload a file.
How can I fix this?
java.lang.IllegalStateException: Unable to process parts as no multi-part configuration has been provided
Rest End point
#PostMapping(path = "/file", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public void uploadAssessment(#RequestParam("file") MultipartFile file) {
System.out.println("Reached here with file ");
}
My Test
LinkedMultiValueMap<String, Object> parameters =
new LinkedMultiValueMap<String, Object>();
parameters.add(
"file",
new org.springframework.core.io.ClassPathResource("abc.txt")
);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<LinkedMultiValueMap<String, Object>> entity =
new HttpEntity<LinkedMultiValueMap<String, Object>>(parameters, headers);
ResponseEntity<String> response =
restTemplate.exchange(uri, HttpMethod.POST, entity, Object.class);

How to send LocalDate in RestTemplate parameter

In below I called web service with String parameter named "samana"
String samana= "000ABC";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
HttpEntity<String> requestEntity = new HttpEntity<String>(null, headers);
Table res = restTemplate
.exchange("http://localhost:8090/tharindu/findAllComputers?saman=").concat(samana), HttpMethod.GET, requestEntity, Table.class)
.getBody();
How to pass LocalDate parameter in RestTemplate webservice
LocalDate samana = LocalDate.now();
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
HttpEntity<String> requestEntity = new HttpEntity<String>(null, headers);
Table res = restTemplate
.exchange("http://localhost:8090/tharindu/findAllComputers?saman=").concat(samana), HttpMethod.GET, requestEntity, Table.class)
.getBody();

HttpClientErrorException$BadRequest: 400 null with RestTemplate 2.1.4.RELEASE

I have an SpringBoot 2.1.4.RELEASE app. that uses a third party API.
With Postman VersiĆ³n 6.7.4.
I authenticate with this URL:
https://bonanza.com:7688/pecador/api/v1/auth
and in the body: { "username": "nunito.calzada#gmail.com","password": "sdfhhskj$(I$" }
and it works perfectly
I have implemented this method:
protected String authToken (Authentication auth) {
// Request Header
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Accept", "application/json");
// Request Body
MultiValueMap<String, String> parametersMap = new LinkedMultiValueMap<String, String>();
parametersMap.add("username", auth.getName());
parametersMap.add("password", (String)auth.getCredentials());
// Request Entity
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(parametersMap, headers);
// RestTemplate
RestTemplate restTemplate = new RestTemplate();
// POST Login
ResponseEntity<String> response = restTemplate.exchange("https://bonanza.com:7688/pecador/api/v1/auth", HttpMethod.POST, requestEntity, String.class);
HttpHeaders responseHeaders = response.getHeaders();
List<String> list = responseHeaders.get("Authorization");
return list == null || list.isEmpty() ? null : list.get(0);
}
but I have this error:
2019-04-25 19:55 [http-nio-2233-exec-2] ERROR i.i.w.a.e.RestResponseEntityExceptionHandler.handleInternal(95) - 500 Status Code
org.springframework.web.client.HttpClientErrorException$BadRequest: 400 null
at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:79)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:122)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:102)
at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:778)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:736)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:670)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:579)
I also tried reple auth.getName() with "nunito.calzada#gmail.com" and (String)auth.getCredentials() with "sdfhhskj$(I$" with the same result
Testing with Postman, I set the Content-Type: application/json in the header:
I also tried this code with the same result:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Accept", "application/json");
//Request Body
MultiValueMap<String, String> parametersMap = new LinkedMultiValueMap<String, String>();
parametersMap.add("username", "ricard.olle#gmail.com");
parametersMap.add("password", "Iconofcoil100#");
HttpEntity<?> httpEntity = new HttpEntity<Object>(parametersMap, headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response =
restTemplate.exchange( BASE_API_URL + "auth", HttpMethod.POST, httpEntity,String.class);
HttpHeaders responseHeaders = response.getHeaders();
List<String> list = responseHeaders.get("Authorization");
return list == null || list.isEmpty() ? null : list.get(0);
Your line:
// Request Entity
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(parametersMap, headers);
is wrong.
Only is necessary to do:
HttpEntity<?> httpEntity = new HttpEntity<Object>(parametersMap, requestHeaders);
because parametersMap is a MultiValueMap but you declare also HttpEntity with a type MultiValueMap, and is not correct is this case.
EDIT:
Ok, MultiValueMap is for petitions "MediaType.APPLICATION_FORM_URLENCODED". Your case is "MediaType.APPLICATION_JSON".
You can create a object that wrap username and password and send this object.
For example:
public class ObjectRequest {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
And then:
ObjectRequest obr = new ObjectRequest();
obr.setUsername("nunito.calzada#gmail.com");
obr.setPassword("sdfhhskj$(I$");
And put this object as object in the HttpEntity:
HttpEntity<ObjectRequest> requestEntity = new HttpEntity<ObjectRequest>(obr, headers);
This will transform the object to json automatically.
How about this?
protected String authToken (Authentication auth) {
Map<String, String> body = Map.of(
"username", auth.getName(),
"password", (String)auth.getCredentials());
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.postForEntity("https://bonanza.com:7688/pecador/api/v1/auth", body, String.class);
HttpHeaders responseHeaders = response.getHeaders();
List<String> list = responseHeaders.get("Authorization");
return list == null || list.isEmpty() ? null : list.get(0);
}

How to set an "Accept:" header on Spring RestTemplate request?

I want to set the value of the Accept: in a request I am making using Spring's RestTemplate.
Here is my Spring request handling code
#RequestMapping(
value= "/uom_matrix_save_or_edit",
method = RequestMethod.POST,
produces="application/json"
)
public #ResponseBody ModelMap uomMatrixSaveOrEdit(
ModelMap model,
#RequestParam("parentId") String parentId
){
model.addAttribute("attributeValues",parentId);
return model;
}
and here is my Java REST client:
public void post(){
MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
params.add("parentId", "parentId");
String result = rest.postForObject( url, params, String.class) ;
System.out.println(result);
}
This works for me; I get a JSON string from the server side.
My question is: how can I specify the Accept: header (e.g. application/json,application/xml, ... ) and request method (e.g. GET,POST, ... ) when I use RestTemplate?
I suggest using one of the exchange methods that accepts an HttpEntity for which you can also set the HttpHeaders. (You can also specify the HTTP method you want to use.)
For example,
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<>("body", headers);
restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
I prefer this solution because it's strongly typed, ie. exchange expects an HttpEntity.
However, you can also pass that HttpEntity as a request argument to postForObject.
HttpEntity<String> entity = new HttpEntity<>("body", headers);
restTemplate.postForObject(url, entity, String.class);
This is mentioned in the RestTemplate#postForObject Javadoc.
The request parameter can be a HttpEntity in order to add additional
HTTP headers to the request.
You could set an interceptor "ClientHttpRequestInterceptor" in your RestTemplate to avoid setting the header every time you send a request.
public class HeaderRequestInterceptor implements ClientHttpRequestInterceptor {
private final String headerName;
private final String headerValue;
public HeaderRequestInterceptor(String headerName, String headerValue) {
this.headerName = headerName;
this.headerValue = headerValue;
}
#Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
request.getHeaders().set(headerName, headerValue);
return execution.execute(request, body);
}
}
Then
List<ClientHttpRequestInterceptor> interceptors = new ArrayList<ClientHttpRequestInterceptor>();
interceptors.add(new HeaderRequestInterceptor("Accept", MediaType.APPLICATION_JSON_VALUE));
RestTemplate restTemplate = new RestTemplate();
restTemplate.setInterceptors(interceptors);
If, like me, you struggled to find an example that uses headers with basic authentication and the rest template exchange API, this is what I finally worked out...
private HttpHeaders createHttpHeaders(String user, String password)
{
String notEncoded = user + ":" + password;
String encodedAuth = Base64.getEncoder().encodeToString(notEncoded.getBytes());
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Authorization", "Basic " + encodedAuth);
return headers;
}
private void doYourThing()
{
String theUrl = "http://blah.blah.com:8080/rest/api/blah";
RestTemplate restTemplate = new RestTemplate();
try {
HttpHeaders headers = createHttpHeaders("fred","1234");
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<String> response = restTemplate.exchange(theUrl, HttpMethod.GET, entity, String.class);
System.out.println("Result - status ("+ response.getStatusCode() + ") has body: " + response.hasBody());
}
catch (Exception eek) {
System.out.println("** Exception: "+ eek.getMessage());
}
}
Calling a RESTful API using RestTemplate
Example 1:
RestTemplate restTemplate = new RestTemplate();
// Add the Jackson message converter
restTemplate.getMessageConverters()
.add(new MappingJackson2HttpMessageConverter());
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Basic XXXXXXXXXXXXXXXX=");
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
restTemplate.getInterceptors()
.add(new BasicAuthorizationInterceptor(USERID, PWORD));
String requestJson = getRequetJson(Code, emailAddr, firstName, lastName);
response = restTemplate.postForObject(URL, requestJson, MYObject.class);
Example 2:
RestTemplate restTemplate = new RestTemplate();
String requestJson = getRequetJson(code, emil, name, lastName);
HttpHeaders headers = new HttpHeaders();
String userPass = USERID + ":" + PWORD;
String authHeader =
"Basic " + Base64.getEncoder().encodeToString(userPass.getBytes());
headers.set(HttpHeaders.AUTHORIZATION, authHeader);
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
HttpEntity<String> request = new HttpEntity<String>(requestJson, headers);
ResponseEntity<MyObject> responseEntity;
responseEntity =
this.restTemplate.exchange(URI, HttpMethod.POST, request, Object.class);
responseEntity.getBody()
The getRequestJson method creates a JSON Object:
private String getRequetJson(String Code, String emailAddr, String name) {
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.createObjectNode();
((ObjectNode) rootNode).put("code", Code);
((ObjectNode) rootNode).put("email", emailAdd);
((ObjectNode) rootNode).put("firstName", name);
String jsonString = null;
try {
jsonString = mapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(rootNode);
}
catch (JsonProcessingException e) {
e.printStackTrace();
}
return jsonString;
}
Short solution without HttpHeaders creating:
RequestEntity<Void> request = RequestEntity.post(URI.create(url))
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
// any other headers
.header("PRIVATE-TOKEN", "token")
.build();
ResponseEntity<String> response = restTemplate.exchange(request, String.class);
return response.getBody();
UPDATE: but in case specific headers HttpHeaders become simple:
RequestEntity.post(URI.create(AMOCRM_URL + url))
.contentType(MediaType.APPLICATION_JSON)
.headers(
new HttpHeaders() {{
setBearerAuth(getAccessToken());
}})
.body(...)
Here is a simple answer. Hope it helps someone.
import org.springframework.boot.devtools.remote.client.HttpHeaderInterceptor;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.web.client.RestTemplate;
public String post(SomeRequest someRequest) {
// create a list the headers
List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
interceptors.add(new HttpHeaderInterceptor("Accept", MediaType.APPLICATION_JSON_VALUE));
interceptors.add(new HttpHeaderInterceptor("ContentType", MediaType.APPLICATION_JSON_VALUE));
interceptors.add(new HttpHeaderInterceptor("username", "user123"));
interceptors.add(new HttpHeaderInterceptor("customHeader1", "c1"));
interceptors.add(new HttpHeaderInterceptor("customHeader2", "c2"));
// initialize RestTemplate
RestTemplate restTemplate = new RestTemplate();
// set header interceptors here
restTemplate.setInterceptors(interceptors);
// post the request. The response should be JSON string
String response = restTemplate.postForObject(Url, someRequest, String.class);
return response;
}

Resources