Spring cloud open Feign Not ignoring null Values while Encoding - spring-boot

I am working on a Spring boot application. We are using Spring cloud open Feign for making rest calls. We are using the default GsonEncoder(), but for some reason gson is not excluding the null properties while encoding the payload.
Config:
return Feign.builder()
.options(ApiOptions())
.encoder(new GsonEncoder())
.decoder(new GsonDecoder())
.target(ApiClient.class, "URL");
Client:
#FunctionalInterface
#FeignClient(
value = "apiTest",
url = "urlHere"
)
public interface ApiClient {
#PostMapping("path/to/service")
AiResponse getDetails(ApiRequest apiRequest);
}
ApiRequest.java:
public class ApiRequest {
private String userName;
private String userId;
private String password;
//#setters and getters
}
But while making the request, the Request Body is :
{
"userName" : "test,
"userId" : null,
"password": "password"
}
My Understanding is that Gson should automatically remove the null while serializing the Request Body. But i can see null properties exist in request.
I even tried with Custom Encoders (Jackson from below):
https://github.com/OpenFeign/feign/blob/master/jackson/src/main/java/feign/jackson/JacksonEncoder.java
As per below, it should not include null while serialzing the requestBody, but still i can see null values being passed in request.
https://github.com/OpenFeign/feign/blob/master/jackson/src/main/java/feign/jackson/JacksonEncoder.java#L39
Below are the dependencies:
Spring clou version : 2020.0.2
org.springframework.cloud:spring-cloud-starter-openfeign
io.github.openfeign:feign-gson:9.5.1
Any suggestions would be really helpful. Thanks in Advance.!

You need to provide OpenFeign with custom Encoder to let it skip nulls.
In my case this beans helps me.
#Configuration
public class ExternalApiConfiguration {
#Bean
public Feign.Builder feignBuilder() {
return Feign.builder()
.contract(new SpringMvcContract());
}
#Bean("feignObjectMapper")
public ObjectMapper feignObjectMapper() {
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
return objectMapper;
}
#Bean
public Encoder feignEncoder(#Qualifier("feignObjectMapper") ObjectMapper objectMapper) {
HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(objectMapper);
ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(jacksonConverter);
return new SpringEncoder(objectFactory);
}
And use this configuration if FeignClient
#FeignClient(configuration = ExternalApiConfiguration.class)

Related

Not able to call SOAP API in WebServiceGatewaySupport by Spring WebServiceTemplate - Need help to fix this issue

I am trying to call SOAP API in Java Spring Boot using WebServiceGatewaySupport by Spring WebServiceTemplate
Config java class
public WebServiceTemplate createWebServiceTemplate(Jaxb2Marshaller marshaller, ClientInterceptor clientInterceptor) {
WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
//SOAP URL
webServiceTemplate.setDefaultUri("http://host/Services.asmx");
//Auth ---It seems issue is here only????? need to check
webServiceTemplate.setMessageSender(new Authentication());
webServiceTemplate.setMarshaller(marshaller);
webServiceTemplate.setUnmarshaller(marshaller);
webServiceTemplate.afterPropertiesSet();
webServiceTemplate.setCheckConnectionForFault(true);
webServiceTemplate.setInterceptors((ClientInterceptor[]) Arrays.asList(createLoggingInterceptor()).toArray());
return webServiceTemplate;
}
SOAP Client Call
public class TicketClient extends WebServiceGatewaySupport {
public String getTicket(Ticket req) {
System.out.println("test inside webservice support1");
response = (AcquireTicketResponse) getWebServiceTemplate().marshalSendAndReceive(req);
Authentication Class
public class Authentication extends HttpUrlConnectionMessageSender {
#Override protected void prepareConnection(HttpURLConnection connection) {
String userpassword = username+":"+password+":"+domain;
String encoded =
Base64.getEncoder().withoutPadding().encodeToString(userpassword.getBytes(StandardCharsets.UTF_8));
connection.setRequestProperty("Authorization", "Basic "+encoded); connection.setRequestProperty("Content-Type", "application/xml"); super.prepareConnection(connection);
}
Not using Authetication class and add the above into
ClientInterceptor
public class SoapLoggingInterceptor implements ClientInterceptor {
#Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
String username="test";
String password="test";
String domain = "#test";
String userpassword = username+":"+password+domain;
String encoded = Base64.getEncoder().withoutPadding().encodeToString(userpassword.getBytes(StandardCharsets.UTF_8));
messageContext.setProperty("Authorization", "Basic "+encoded);
messageContext.setProperty("Content-type", "XML");
Case -1 --->When I passed (user, pwd, domain and content-type) through messagesender, content type is taking but throwed "BAD REQUEST ERROR 400"....When i comment contenttype property, then it throwed "INTERNAL SERVER ERROR 500".
Case-2...when I passed (user, pwd, domain and content-type) through ClientInterceptor , always it throwed "INTERNAL SERVER ERROR 500"......It seems Authentication properties for the service are not going to API call.............................Please suggest some options
Both the cases, Authentication is not passing to service, if i comment,Authentication code (userid/pwd/domain) in both cases also...no efforts in output
After setting the user ID/pwd
#Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
String username="test";
String password="test";
String domain = "#test";
String userpassword = username+":"+password+domain;
byte[] userpassword = (username+":"+password).getBytes(StandardCharsets.UTF_8);
String encoded = Base64.getEncoder().encodeToString(userpassword);
ByteArrayTransportOutputStream os = new
ByteArrayTransportOutputStream();
try {
TransportContext context = TransportContextHolder.getTransportContext();
WebServiceConnection conn = context.getConnection();
((HeadersAwareSenderWebServiceConnection) conn).addRequestHeader("Authorization", "Basic " + encoded);
} catch (IOException e) {
throw new WebServiceIOException(e.getMessage(), e);
}
First of all don't set the content type Spring WebServices will do that for you, messing around with that will only make things worse.
You should get the WebServiceConnection and cast that to a HeadersAwareSenderWebServiceConnection to add a header.
public class BasicAuthenticationInterceptor implements ClientInterceptor {
#Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
String username="test#test";
String password="test";
byte[] userpassword = (username+":"+password).getBytes(UTF_8);
String encoded = Base64.getEncoder().encodeToString(userpassword);
WebServiceConnection conn = TransportContext.getConnection();
((HeadersAwareSenderWebServiceConnection) conn).addHeader("Authorization", "Basic " + encoded);
}
}
You also need to configure it. Assuming it is a bean don't call afterPropertiesSet (and ofcourse you are now using the ClientInterceptor remove the new Authentication() for your customized message sender.
The List<ClientInterceptor> will automatically create a list with all the interceptors so you can easily inject them.
#Bean
public WebServiceTemplate createWebServiceTemplate(Jaxb2Marshaller marshaller, List<ClientInterceptor> clientInterceptors) {
WebServiceTemplate webServiceTemplate = new WebServiceTemplate(marshaller);
//SOAP URL
webServiceTemplate.setDefaultUri("http://host/Services.asmx");
webServiceTemplate.setCheckConnectionForFault(true);
webServiceTemplate.setInterceptors(clientInterceptors);
return webServiceTemplate;
}
If this doesn't work there is something else you are doing wrong and you will need to get in touch with the server developers and get more information on the error.
Update:
Apparently you also need to provide a SOAP Action in your request, which you currently don't. For this you can specify the SoapActionCallback in the marshalSendAndReceive method. Which action to specify you can find in the WSDL you are using.
SoapActionCallback soapAction = new SoapActionCallback("SoapActionToUse");
response = (AcquireTicketResponse) getWebServiceTemplate().marshalSendAndReceive(req, soapAction);

Reuse existing token rather than requesting it on every request in spring boot + Retrofit app

I have a spring boot application that uses Retrofit to make requests to a secured server.
My endpoints:
public interface ServiceAPI {
#GET("/v1/isrcResource/{isrc}/summary")
Call<ResourceSummary> getResourceSummaryByIsrc(#Path("isrc") String isrc);
}
public interface TokenServiceAPI {
#FormUrlEncoded
#POST("/bbcb6b2f-8c7c-4e24-86e4-6c36fed00b78/oauth2/v2.0/token")
Call<Token> obtainToken(#Field("client_id") String clientId,
#Field("scope") String scope,
#Field("client_secret") String clientSecret,
#Field("grant_type") String grantType);
}
Configuration class:
#Bean
Retrofit tokenAPIFactory(#Value("${some.token.url}") String tokenUrl) {
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(tokenUrl)
.addConverterFactory(JacksonConverterFactory.create());
return builder.build();
}
#Bean
Retrofit serviceAPIFactory(#Value("${some.service.url}") String serviceUrl, TokenServiceAPI tokenAPI) {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new ServiceInterceptor(clientId, scope, clientSecret, grantType, apiKey, tokenAPI))
.build();
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(repertoireUrl)
.client(okHttpClient)
.addConverterFactory(JacksonConverterFactory.create());
return builder.build();
}
Interceptor to add the Authorization header to every request
public class ServiceInterceptor implements Interceptor {
public ServiceInterceptor(String clientId,
String scope,
String clientSecret,
String grantType,
String apiKey,
TokenServiceAPI tokenAPI) {
this.clientId = clientId;
this.scope = scope;
this.clientSecret = clientSecret;
this.grantType = grantType;
this.apiKey = apiKey;
this.tokenAPI = tokenAPI;
}
#Override
public Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request().newBuilder()
.addHeader(AUTHORIZATION_HEADER, getToken())
.addHeader(API_KEY_HEADER, this.apiKey)
.build();
return chain.proceed(newRequest);
}
private String getToken() throws IOException {
retrofit2.Response<Token> tokenResponse = repertoireTokenAPI.obtainToken(clientId, scope, clientSecret, grantType).execute();
String accessToken = "Bearer " + tokenAPI.body().getAccessToken();
return accessToken;
}
}
This is working as expected, the problem is that the token is being requested for every request rather than using the existing valid one. How can one store the token somewhere and re-use it? I was wondering if Retrofit had a built-in solution.
a possible option with caching:
add caffeiene
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
add #Cacheable("your-token-cache-name") on the method returning the token, looks like getToken above
add max cache size and expiration configuration in application.yml
e.g. 500 entries and 10 minutes for configuration below
spring.cache.cache-names=your-token-cache-name
spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600s
example from: https://www.javadevjournal.com/spring-boot/spring-boot-with-caffeine-cache/

Streaming upload via #Bean-provided RestTemplateBuilder buffers full file

I'm building a reverse-proxy for uploading large files (multiple gigabytes), and therefore want to use a streaming model that does not buffer entire files. Large buffers would introduce latency and, more importantly, they could result in out-of-memory errors.
My client class contains
#Autowired private RestTemplate restTemplate;
#Bean
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
int REST_TEMPLATE_MODE = 1; // 1=streams, 2=streams, 3=buffers
return
REST_TEMPLATE_MODE == 1 ? new RestTemplate() :
REST_TEMPLATE_MODE == 2 ? (new RestTemplateBuilder()).build() :
REST_TEMPLATE_MODE == 3 ? restTemplateBuilder.build() : null;
}
and
public void upload_via_streaming(InputStream inputStream, String originalname) {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setBufferRequestBody(false);
restTemplate.setRequestFactory(requestFactory);
InputStreamResource inputStreamResource = new InputStreamResource(inputStream) {
#Override public String getFilename() { return originalname; }
#Override public long contentLength() { return -1; }
};
MultiValueMap<String, Object> body = new LinkedMultiValueMap<String, Object>();
body.add("myfile", inputStreamResource);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body,headers);
String response = restTemplate.postForObject(UPLOAD_URL, requestEntity, String.class);
System.out.println("response: "+response);
}
This is working, but notice my REST_TEMPLATE_MODE value controls whether or not it meets my streaming requirement.
Question: Why does REST_TEMPLATE_MODE == 3 result in full-file buffering?
References:
How to forward large files with RestTemplate?
How to send Multipart form data with restTemplate Spring-mvc
Spring - How to stream large multipart file uploads to database without storing on local file system -- establishing the InputStream
How to autowire RestTemplate using annotations
Design notes and usage caveats, also: restTemplate does not support streaming downloads
In short, the instance of RestTemplateBuilder provided as an #Bean by Spring Boot includes an interceptor (filter) associated with actuator/metrics -- and the interceptor interface requires buffering of the request body into a simple byte[].
If you instantiate your own RestTemplateBuilder or RestTemplate from scratch, it won't include this by default.
I seem to be the only person visiting this post, but just in case it helps someone before I get around to posting a complete solution, I've found a big clue:
restTemplate.getInterceptors().forEach(item->System.out.println(item));
displays...
org.SF.boot.actuate.metrics.web.client.MetricsClientHttpRequestInterceptor
If I clear the interceptor list via setInterceptors, it solves the problem. Furthermore, I found that any interceptor, even if it only performs a NOP, will introduce full-file buffering.
public class SimpleClientHttpRequestFactory { ...
I have explicitly set bufferRequestBody = false, but apparently this code is bypassed if interceptors are used. This would have been nice to know earlier...
#Override
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
HttpURLConnection connection = openConnection(uri.toURL(), this.proxy);
prepareConnection(connection, httpMethod.name());
if (this.bufferRequestBody) {
return new SimpleBufferingClientHttpRequest(connection, this.outputStreaming);
}
else {
return new SimpleStreamingClientHttpRequest(connection, this.chunkSize, this.outputStreaming);
}
}
public abstract class InterceptingHttpAccessor extends HttpAccessor { ...
This shows that the InterceptingClientHttpRequestFactory is used if the list of interceptors is not empty.
/**
* Overridden to expose an {#link InterceptingClientHttpRequestFactory}
* if necessary.
* #see #getInterceptors()
*/
#Override
public ClientHttpRequestFactory getRequestFactory() {
List<ClientHttpRequestInterceptor> interceptors = getInterceptors();
if (!CollectionUtils.isEmpty(interceptors)) {
ClientHttpRequestFactory factory = this.interceptingRequestFactory;
if (factory == null) {
factory = new InterceptingClientHttpRequestFactory(super.getRequestFactory(), interceptors);
this.interceptingRequestFactory = factory;
}
return factory;
}
else {
return super.getRequestFactory();
}
}
class InterceptingClientHttpRequest extends AbstractBufferingClientHttpRequest { ...
The interfaces make it clear that using InterceptingClientHttpRequest requires buffering body to a byte[]. There is not an option to use a streaming interface.
#Override
public ClientHttpResponse execute(HttpRequest request, byte[] body) throws IOException {

Configuring custom Json Serializer for Spring controller test

I'm testing a controller:
#RestController()
public class MessagesController {
...
}
Using #WebMvcTest annotation:
#RunWith(SpringRunner.class)
#WebMvcTest(value = {MessagesController.class})
public class MessagesControllerTest {
private MockMvc mvc;
....
this.mvc.perform(
get("/messages/{id}", "dummyId")
.contentType(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isOk());
...
But when I launch my test Spring tries to serialize an object of type List> and it fails:
Resolved Exception:
Type = org.springframework.http.converter.HttpMessageNotWritableException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 500
Error message = null
Headers = {Content-Type=[application/json;charset=UTF-8]}
Content type = application/json;charset=UTF-8
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status
Expected :200
Actual :500
When I follow the execution in debug mode I found that the exception is thrown from : com.fasterxml.jackson.databind.ser.std.CollectionSerializer#serializeContents
And it's a JsonMappingException :
com.fasterxml.jackson.databind.JsonMappingException: Unwrapped property requires use of type information: can not serialize without disabling `SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS` (through reference chain: org.springframework.hateoas.Resource["content"]).
I also tried to inject an ObjectMapper into my context, but it's not used. Another ObjectMapper is used in the Serilaization process. This is the ObjectMapper I inject with #Import(HateoasConfiguration.class) on my test class:
#EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL)
#Configuration
public class HateoasConfiguration
{
private static final String SPRING_HATEOAS_OBJECT_MAPPER = "_halObjectMapper";
#Autowired
#Qualifier(SPRING_HATEOAS_OBJECT_MAPPER)
private ObjectMapper springHateoasObjectMapper;
#Bean(name = "objectMapper")
public ObjectMapper objectMapper() {
springHateoasObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
springHateoasObjectMapper.disable(SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS);
springHateoasObjectMapper.registerModules(
new ParameterNamesModule(),
new Jdk8Module(),
new JavaTimeModule(),
new URNModule()
);
return springHateoasObjectMapper;
}
}

Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported for #RequestBody MultiValueMap

Based on the answer for problem with x-www-form-urlencoded with Spring #Controller
I have written the below #Controller method
#RequestMapping(value = "/{email}/authenticate", method = RequestMethod.POST
, produces = {"application/json", "application/xml"}
, consumes = {"application/x-www-form-urlencoded"}
)
public
#ResponseBody
Representation authenticate(#PathVariable("email") String anEmailAddress,
#RequestBody MultiValueMap paramMap)
throws Exception {
if(paramMap == null || paramMap.get("password") == null) {
throw new IllegalArgumentException("Password not provided");
}
}
the request to which fails with the below error
{
"timestamp": 1447911866786,
"status": 415,
"error": "Unsupported Media Type",
"exception": "org.springframework.web.HttpMediaTypeNotSupportedException",
"message": "Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported",
"path": "/users/usermail%40gmail.com/authenticate"
}
[PS: Jersey was far more friendly, but couldn't use it now given the practical restrictions here]
The problem is that when we use application/x-www-form-urlencoded, Spring doesn't understand it as a RequestBody. So, if we want to use this
we must remove the #RequestBody annotation.
Then try the following:
#RequestMapping(
path = "/{email}/authenticate",
method = RequestMethod.POST,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = {
MediaType.APPLICATION_ATOM_XML_VALUE,
MediaType.APPLICATION_JSON_VALUE
})
public #ResponseBody Representation authenticate(
#PathVariable("email") String anEmailAddress,
MultiValueMap paramMap) throws Exception {
if (paramMap == null &&
paramMap.get("password") == null) {
throw new IllegalArgumentException("Password not provided");
}
return null;
}
Note that removed the annotation #RequestBody
answer: Http Post request with content type application/x-www-form-urlencoded not working in Spring
It seems that now you can just mark the method parameter with #RequestParam and it will do the job for you.
#PostMapping( "some/request/path" )
public void someControllerMethod( #RequestParam Map<String, String> body ) {
//work with Map
}
Add a header to your request to set content type to application/json
curl -H 'Content-Type: application/json' -s -XPOST http://your.domain.com/ -d YOUR_JSON_BODY
this way spring knows how to parse the content.
In Spring 5
#PostMapping( "some/request/path" )
public void someControllerMethod( #RequestParam MultiValueMap body ) {
// import org.springframework.util.MultiValueMap;
String datax = (String) body .getFirst("datax");
}
#RequestBody MultiValueMap paramMap
in here Remove the #RequestBody Annotaion
#RequestMapping(value = "/signin",method = RequestMethod.POST)
public String createAccount(#RequestBody LogingData user){
logingService.save(user);
return "login";
}
#RequestMapping(value = "/signin",method = RequestMethod.POST)
public String createAccount( LogingData user){
logingService.save(user);
return "login";
}
like that
Simply removing #RequestBody annotation solves the problem (tested on Spring Boot 2):
#RestController
public class MyController {
#PostMapping
public void method(#Valid RequestDto dto) {
// method body ...
}
}
I met the same problem when I want to process my simple HTML form submission (without using thymeleaf or Spring's form tag) in Spring MVC.
The answer of Douglas Ribeiro will work very well. But just in case, for anyone, like me, who really want to use "#RequestBody" in Spring MVC.
Here is the cause of the problem:
Spring need to ① recognize the "Content-Type", and ② convert the
content to the parameter type we declared in the method's signature.
The 'application/x-www-form-urlencoded' is not supported, because, by
default, the Spring cannot find a proper HttpMessageConverter to do
the converting job, which is step ②.
Solution:
We manually add a proper HttpMessageConverter into the Spring's
configuration of our application.
Steps:
Choose the HttpMessageConverter's class we want to use. For
'application/x-www-form-urlencoded', we can choose
"org.springframework.http.converter.FormHttpMessageConverter".
Add the FormHttpMessageConverter object to Spring's configuration,
by calling the "public void
configureMessageConverters(List<HttpMessageConverter<?>>
converters)" method of the "WebMvcConfigurer" implementation class
in our application. Inside the method, we can add any
HttpMessageConverter object as needed, by using "converters.add()".
By the way, the reason why we can access the value by using "#RequestParam" is:
According to Servlet Specification (Section 3.1.1):
The following are the conditions that must be met before post form
data will be populated to the parameter set: The request is an HTTP
or HTTPS request. 2. The HTTP method is POST. 3. The content type is
application/x-www-form-urlencoded. 4. The servlet has made an initial
call of any of the getParameter family of methods on the request
object.
So, the value in request body will be populated to parameters. But in Spring, you can still access RequestBody, even you can use #RequstBody and #RequestParam at the same method's signature.
Like:
#RequestMapping(method = RequestMethod.POST, consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public String processForm(#RequestParam Map<String, String> inputValue, #RequestBody MultiValueMap<String, List<String>> formInfo) {
......
......
}
The inputValue and formInfo contains the same data, excpet for the type for "#RequestParam" is Map, while for "#RequestBody" is MultiValueMap.
I wrote about an alternative in this StackOverflow answer.
There I wrote step by step, explaining with code. The short way:
First: write an object
Second: create a converter to mapping the model extending the AbstractHttpMessageConverter
Third: tell to spring use this converter implementing a WebMvcConfigurer.class overriding the configureMessageConverters method
Fourth and final: using this implementation setting in the mapping inside your controller the consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE and #RequestBody in front of your object.
I'm using spring boot 2.
#PostMapping(path = "/my/endpoint", consumes = { MediaType.APPLICATION_FORM_URLENCODED_VALUE })
public ResponseEntity<Void> handleBrowserSubmissions(MyDTO dto) throws Exception {
...
}
That way works for me
You can try to turn support on in spring's converter
#EnableWebMvc
#Configuration
public class WebConfig implements WebMvcConfigurer {
#Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
// add converter suport Content-Type: 'application/x-www-form-urlencoded'
converters.stream()
.filter(AllEncompassingFormHttpMessageConverter.class::isInstance)
.map(AllEncompassingFormHttpMessageConverter.class::cast)
.findFirst()
.ifPresent(converter -> converter.addSupportedMediaTypes(MediaType.APPLICATION_FORM_URLENCODED_VALUE));
}
}
Just add an HTTP Header Manager if you are testing using JMeter :

Resources