I am using Spring Boot 2.1.2 and junit-jupiter-api-5.3.2 and I am doing integration testing.
My test case is this:
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.ril.vms.hawkeye.otp.dto.SendOTPRequestDTO;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
#SpringBootTest(classes = MyApplication.class,
webEnvironment = WebEnvironment.RANDOM_PORT)
#ActiveProfiles("sit")
public class OtpControllerIntegrationTest
{
#LocalServerPort
private int port;
#Autowired
private TestRestTemplate restTemplate;
#Test
public void sendOtpTest() throws Exception {
SendOTPRequest otpRequest = new SendOTPRequestDTO();
otpRequest.setClientId("default2");
otpRequest.setTag("tag");
otpRequest.setMobileNumber("9999999999");
ResponseEntity<String> responseEntity = this.restTemplate
.postForEntity("http://localhost:" + port + "/sendOtp", otpRequest, String.class);
assertEquals(201, responseEntity.getStatusCodeValue());
}
}
But I am getting java.lang.NullPointerException at below line.
ResponseEntity<String> responseEntity = this.restTemplate ...
try this template
public ArrayList<ABC> lovApi(LovsRequestDto reqObj) {
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "application/json");
HttpEntity<ABCDto> entity = new HttpEntity<ABCDto>(reqObj, headers);
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
RestTemplate restTemplate = new RestTemplate(requestFactory);
String postUrl = "http://80.111.23.23.33333.....";
ResponseEntity<LovsResponse> postResponse = restTemplate.exchange(postUrl, HttpMethod.POST, entity, LovsResponse.class);
return postResponse.getBody().getLovs_response_details().getLovList();
}
try to create a new restTemplate bean in sendOtpTest mehtods. you get null point because this.restTemplate is not be instation; wish help you;
Related
I have a rest controller, which has simple CRUD operations. I am trying to write integration test.
Below is my RestController:
package com.gasx.corex.scheduler.controller;
import java.awt.*;
import java.util.List;
import com.gasx.corex.scheduler.service.SchedulerJobServiceI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.gasx.corex.ext.scheduler.domain.SchedulerJob;
import com.gasx.corex.scheduler.service.SchedulerJobService;
#RestController
#RequestMapping("/gasx/restscd")
public class SchedulerJobController {
#Autowired
private SchedulerJobServiceI schedulerJobService;
#RequestMapping(method = RequestMethod.GET , path="/getschedulerjobs" , produces= MediaType.APPLICATION_JSON_VALUE)
public List<SchedulerJob> getAllSchedulerJobs() {
return schedulerJobService.getAllSchedulerJobs();
}
#RequestMapping(method = RequestMethod.POST, value = "/addschedulerjob")
public void addSchedulerJob(#RequestBody SchedulerJob schedulerJob) {
schedulerJobService.addSchedulerJob(schedulerJob);
}
#RequestMapping(method = RequestMethod.POST, value = "/updateschedulerjob")
public void updateSchedulerJob(#RequestBody SchedulerJob schedulerJob) {
schedulerJobService.updateSchedulerJob(schedulerJob);
}
#RequestMapping(method = RequestMethod.POST, value = "/deleteschedulerjob")
public void deleteSchedulerJob(#RequestBody SchedulerJob schedulerJob) {
schedulerJobService.deleteSchedulerJob(schedulerJob);
}
}
I have written Integration test for all of the endpoints in RestController
Integration test class :-
package com.gasx.corex.ext.scheduler.integrationtest.domain;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gasx.corex.base.configuration.CoreConfiguration;
import com.gasx.corex.ext.scheduler.domain.SchedulerJob;
import com.gasx.corex.ext.scheduler.domain.utils.SchedulerJobType;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.context.annotation.Import;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.http.HttpHeaders;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.WebApplicationContext;
import sun.security.krb5.internal.Ticket;
import org.springframework.http.HttpMethod;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import java.io.IOException;
import java.util.Base64;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT , properties = {
"management.server.port=0", "management.context-path=/admin" ,"security.basic.enabled=false"} )
#EnableAutoConfiguration
#ContextConfiguration( classes = {CoreConfiguration.class } )
#AutoConfigureMockMvc
public class SchedulerJobTestInt {
#LocalServerPort
private int port ;
#Autowired
private TestRestTemplate testRestTemplate;
#Autowired
WebApplicationContext context;
#Autowired
private MockMvc mockMvc;
#Before
public void setUp() {
this.mockMvc = MockMvcBuilders
.webAppContextSetup(context)
.build();
}
#Test
public void getAllSchedulerJobsIntTest() throws Exception {
ResponseEntity<String> response = testRestTemplate.getForEntity("http://localhost:" + port +"/gasx/restscd/getschedulerjobs", String.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
ObjectMapper objectMapper = new ObjectMapper();
JsonNode responseJson = objectMapper.readTree(response.getBody());
assertThat(responseJson.isMissingNode()).isFalse();
assertThat(responseJson.toString()).isEqualTo("[]");
}
#Test
public void addSchedulerJobIntTest() throws Exception{
SchedulerJob schedulerJob = new SchedulerJob();
schedulerJob.setName("ALB Cleanup");
schedulerJob.setDescription("Cleanup of alb jobs. Please do not deactivate!");
schedulerJob.setType(SchedulerJobType.REST);
schedulerJob.setActive(true);
schedulerJob.setStartMissedRun(false);
schedulerJob.setCategory("SYSTEM");
schedulerJob.setCronExpression(null);
schedulerJob.setScheme("testScheme");
schedulerJob.setIdRegion(1);
schedulerJob.setAlbEndpoint("testAlbEndPoint");
schedulerJob.setAlbPayload("SCHED_ALB");
schedulerJob.setAlbPrio(1);
schedulerJob.setAlbJobUser("MKRAUS");
schedulerJob.setScriptParams("testScriptParams");
schedulerJob.setShellScriptParams("clear_tmp 15");
schedulerJob.setSoapEndpointAlias("");
schedulerJob.setSoapImportPath("CORE/CORE2003/imp/price");
schedulerJob.setSoapExportPath("testExportPath");
schedulerJob.setSoapPayload("<api:readPartnersByIdRequest>");
schedulerJob.setSoapAction("urn:readPartnersById");
schedulerJob.setRestEndpointAlias("testEndpointAlias");
schedulerJob.setRestUrl("testUrl");
schedulerJob.setRestEntityContent("");
schedulerJob.setRestExportPath("testRestExportPath");
schedulerJob.setHookScriptName("testHookScriptName");
schedulerJob.setMinutes("");
schedulerJob.setHours("");
String plainCredentials="gasx:gasx!";
String base64Credentials = Base64.getEncoder().encodeToString(plainCredentials.getBytes());
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + base64Credentials);
headers.add("Accept" , "application/json");
HttpEntity<String> entity = new HttpEntity<String>(asJsonString(schedulerJob), headers);
// ResponseEntity<Void> response = testRestTemplate.postForEntity("http://localhost:"+port +"/gasx/restscd/addschedulerjob", entity,Void.class);
ResponseEntity<Void> response = testRestTemplate.postForEntity("http://localhost:" + port +"/gasx/restscd/addschedulerjob", asJsonString(schedulerJob),Void.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
private String createURLWithPort(String uri) {
return "http://localhost:" + port + uri;
}
#Test
public void updateSchedulerJobTest(){
SchedulerJob schedulerJob = new SchedulerJob();
schedulerJob.setName("ALB Cleanup");
schedulerJob.setDescription("Cleanup of alb jobs. Please do not deactivate!");
schedulerJob.setType(SchedulerJobType.REST);
schedulerJob.setActive(true);
schedulerJob.setStartMissedRun(false);
schedulerJob.setCategory("SYSTEM");
schedulerJob.setCronExpression(null);
schedulerJob.setScheme("testScheme");
schedulerJob.setIdRegion(1);
schedulerJob.setAlbEndpoint("testAlbEndPoint");
schedulerJob.setAlbPayload("SCHED_ALB");
schedulerJob.setAlbPrio(1);
schedulerJob.setAlbJobUser("MKRAUS");
schedulerJob.setScriptParams("testScriptParams");
schedulerJob.setShellScriptParams("clear_tmp 15");
schedulerJob.setSoapEndpointAlias("");
schedulerJob.setSoapImportPath("CORE/CORE2003/imp/price");
schedulerJob.setSoapExportPath("testExportPath");
schedulerJob.setSoapPayload("<api:readPartnersByIdRequest>");
schedulerJob.setSoapAction("urn:readPartnersById");
schedulerJob.setRestEndpointAlias("testEndpointAlias");
schedulerJob.setRestUrl("testUrl");
schedulerJob.setRestEntityContent("");
schedulerJob.setRestExportPath("testRestExportPath");
schedulerJob.setHookScriptName("testHookScriptName");
schedulerJob.setMinutes("");
schedulerJob.setHours("");
ResponseEntity<Void> response = testRestTemplate.withBasicAuth("gasx" ,"gasx!").postForEntity("http://localhost:" + port +"/gasx/restscd/updateschedulerjob", schedulerJob,Void.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
#Test
public void deleteSchedulerJob(){
SchedulerJob schedulerJob = new SchedulerJob();
schedulerJob.setName("ALB Cleanup");
schedulerJob.setDescription("Cleanup of alb jobs. Please do not deactivate!");
schedulerJob.setType(SchedulerJobType.REST);
schedulerJob.setActive(true);
schedulerJob.setStartMissedRun(false);
schedulerJob.setCategory("SYSTEM");
schedulerJob.setCronExpression(null);
schedulerJob.setScheme("testScheme");
schedulerJob.setIdRegion(1);
schedulerJob.setAlbEndpoint("testAlbEndPoint");
schedulerJob.setAlbPayload("SCHED_ALB");
schedulerJob.setAlbPrio(1);
schedulerJob.setAlbJobUser("MKRAUS");
schedulerJob.setScriptParams("testScriptParams");
schedulerJob.setShellScriptParams("clear_tmp 15");
schedulerJob.setSoapEndpointAlias("");
schedulerJob.setSoapImportPath("CORE/CORE2003/imp/price");
schedulerJob.setSoapExportPath("testExportPath");
schedulerJob.setSoapPayload("<api:readPartnersByIdRequest>");
schedulerJob.setSoapAction("urn:readPartnersById");
schedulerJob.setRestEndpointAlias("testEndpointAlias");
schedulerJob.setRestUrl("testUrl");
schedulerJob.setRestEntityContent("");
schedulerJob.setRestExportPath("testRestExportPath");
schedulerJob.setHookScriptName("testHookScriptName");
schedulerJob.setMinutes("");
schedulerJob.setHours("");
ResponseEntity<Void> response = testRestTemplate.withBasicAuth("gasx" ,"gasx!").postForEntity("http://localhost:" + port +"/gasx/restscd/deleteschedulerjob", schedulerJob,Void.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
public static String asJsonString(final Object obj) {
try {
return new ObjectMapper().writeValueAsString(obj);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
My problems:
1.)Wheneever I put breakpoint in Rest Controller, it doesnt' stop there, actually it is not getting invoked.
2.)When I run the test for GET it returns sign-in html page from response.getBody()
3.)When I run the test for POST it returns status 401 unauthorized
tried numerious possible solutions on google
even disabled spring security by commenting the the configuration still it doesn't work.
I can call the same Rest Controller from my Unit test and can stop the breakpoints.
My security configurations:-
package com.gasx.corex.scheduler.server;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import com.gasx.corex.ext.user.domain.DefaultRoles;
#Configuration
#EnableWebSecurity
#Order(1)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
// #formatter:off
httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.httpBasic().and()
.authorizeRequests()
.antMatchers("/gasx/**").hasAnyAuthority(DefaultRoles.ROOT.getName(), DefaultRoles.ADMIN.getName(), DefaultRoles.ACTUATOR.getName())
.antMatchers("/webjars/**").hasAnyAuthority(DefaultRoles.ROOT.getName(), DefaultRoles.ADMIN.getName(), DefaultRoles.ACTUATOR.getName())
.antMatchers("/monitor/**").hasAnyAuthority(DefaultRoles.ROOT.getName(), DefaultRoles.ACTUATOR.getName())
// dev urls
.antMatchers("/h2-console/**").hasAuthority(DefaultRoles.ROOT.getName())
.antMatchers("/swagger*/**","/v2/**").hasAnyAuthority(DefaultRoles.ROOT.getName(), DefaultRoles.ADMIN.getName())
.anyRequest().denyAll();
// #formatter:on
httpSecurity.csrf().disable();
httpSecurity.headers().frameOptions().disable();
}
}
Tried one more thing, added below class to my package :-
package com.gasx.corex.ext.scheduler.integrationtest.domain;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
public class AllowAnonymousWebAccess extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity web) throws Exception {
web.antMatcher("**/*").anonymous();
}
}
and now it gives 404.
I don't know anything about this project's SecurityConfiguration (you should provide some more information about it), but I think that you should provide some authorization data (Like a JWT in the Authorization header, or so)
Could you give me some more information about the SecurityConfig? (look for org.springframework.security.config.something.something... imports )
EDIT
I took a look at your code, and actually this part
httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.httpBasic().and()
.authorizeRequests()
.antMatchers("/gasx/**").hasAnyAuthority(DefaultRoles.ROOT.getName(), DefaultRoles.ADMIN.getName(), DefaultRoles.ACTUATOR.getName())
is protecting your API with an httpBasic type authorization. You shold provide the credentials in the header to test your application.
Background: Search form in a webapp, with an auto-complete/suggestion. Using jQuery's autocomplete, suggestions are shown after typing a few characters. These suggesitons are retrieved as JSON data from one of the webapp's controllers.
Issue: I am testing the application via the HtmlUnit Integration of Spring Test, which works fine for Text/Html Pages, but for the JSON responses here, the setup seems to fail (see error below).
Manually testing (the actual webapp) via Browser works and fetching JSON from "real" pages works as well ( see "json()" test) -> Should testing JSON responses work via HtmlUnit / Spring Test setup and if yes, what am I doing wrong?
Update (2017-06-21):
Using
#ResponseBody String
and building the JSON "manually" (not letting Spring automagically doing it) works; not really what I wanted, but at least I can properly test it this way ...
Test:
package my.project;
import com.gargoylesoftware.htmlunit.*;
import org.junit.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.*;
import org.springframework.test.*;
import org.springframework.web.context.support.GenericWebApplicationContext;
import javax.servlet.ServletException;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {TestWebAppConfig.class,
// avoid context caching
MyControllerIT.class})
#WebAppConfiguration
public class MyControllerIT {
protected static final String SERVER_URL = "http://localhost";
protected WebClient webClient;
protected MockHttpServletRequest request;
protected MockHttpServletResponse response;
#Autowired
protected GenericWebApplicationContext webApplicationContext;
#Before
public void setUp() throws Exception {
this.request = new MockHttpServletRequest();
this.request.setServerName("Gondor.Osgiliath");
this.response = new MockHttpServletResponse();
this.webClient = this.initClient();
}
protected final WebClient initClient() throws ServletException {
DefaultMockMvcBuilder mockMvcBuilder = MockMvcBuilders.webAppContextSetup(this.webApplicationContext);
MockMvc mockMvc = mockMvcBuilder.build();
WebClient webClient = new WebClient();
webClient.setWebConnection(new MockMvcWebConnection(mockMvc));
return webClient;
}
// https://stackoverflow.com/questions/2932857/html-handling-a-json-response
#Test
public void json() throws Exception {
webClient = new WebClient(BrowserVersion.INTERNET_EXPLORER, "some.proxy", 7890);
Page page = webClient.getPage("https://stackoverflow.com/users/flair/97901.json");
WebResponse webResponse = page.getWebResponse();
String contentType = webResponse.getContentType();
String contentAsString = webResponse.getContentAsString();
}
#Test
public void suggestShouldReturnJSON() throws Exception {
Page page = webClient.getPage(SERVER_URL + MyController.SUGGEST_URL + "?term=asdf");
WebResponse webResponse = page.getWebResponse();
String contentType = webResponse.getContentType();
String contentAsString = webResponse.getContentAsString();
}
#Test
public void suggestShouldReturnJSONViaMockMvc() throws Exception {
MockMvc springMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
ResultActions resultActions = springMvc.perform(MockMvcRequestBuilders
.get(MyController.SUGGEST_URL + "?term=asdf")
.accept(MediaType.APPLICATION_JSON_VALUE));
resultActions.andDo(MockMvcResultHandlers.print());
}
}
Controller:
package my.project;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Arrays;
import java.util.List;
#Controller
public class MyController {
public static final String SUGGEST_URL = "/suggest";
//http://api.jqueryui.com/autocomplete/#option-source
#RequestMapping(value = {SUGGEST_URL,}, produces = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody
List<Suggestion> suggest(#RequestParam(name = "term") String term) {
return Arrays.asList(new Suggestion("label1", "value1"), new Suggestion("label2", "value2"));
}
}
Config (Thymeleaf omitted for the moment):
package my.project;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#EnableWebMvc
#ComponentScan(basePackages = {"my.project.*",})
#Configuration
#Import(ThymeleafConfig.class)
abstract class TestWebAppConfig extends WebMvcConfigurerAdapter {
}
Error:
com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException: 406 Not Acceptable for http://localhost/suggest?term=asdf
at com.gargoylesoftware.htmlunit.WebClient.throwFailingHttpStatusCodeExceptionIfNecessary(WebClient.java:571)
at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:396)
at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:304)
at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:451)
at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:436)
at my.project.MyControllerIt.suggestShouldReturnJSON(MyControllerIt.java:
...
I have this code :
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestTemplate;
#SpringBootApplication
public class Application {
public static void main(String args[]) {
SpringApplication.run(Application.class);
}
#Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
RestTemplate restTemplate = builder.rootUri("http://login.xxx.com/").basicAuthorization("user", "pass").build();
return restTemplate;
}
#Bean
public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
return args -> {
restTemplate.getForObject(
"http://login.xxx.com/ws/YY/{id}", YY.class,
"123");
};
}
}
but I'm getting this error :
Caused by: org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class com.xxx.test.YY] and content type [application/xml;charset=ISO-8859-1]
How can I add MediaType.APPLICATION_JSON to the header and add the header to the restTemplate and do getForObject ?
You don't need to add the accept header when using any of the get methods, RestTemplate will do that automatically. If you look inside RestTemplate's constructor, you can see that it automatically checks the classpath and add common message converters. So you may need to check you're classpath (or step into the constructor to see which converters it autodetects.
If you need to add custom headers, like Bearer authentication, you can always use the exchange method to build the request exactly as you like. Here is an example that should work, I have added the Jackson message converter explicetly, so you should get an compilation error if it is not in your classpath.
import java.net.URI;
import java.util.Map;
import com.google.common.collect.Lists;
import org.springframework.http.*;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;
public class Main {
public static void main(String[] args) throws Exception {
RestTemplate template = new RestTemplate();
template.setMessageConverters(Lists.newArrayList(new MappingJackson2HttpMessageConverter()));
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Lists.newArrayList(MediaType.APPLICATION_JSON));
ResponseEntity<Map> forEntity = template.exchange(new RequestEntity<>(null, headers, HttpMethod.GET, new URI("https://docs.tradable.com/v1/accounts")), Map.class);
System.out.println("forEntity.getBody() = " + forEntity.getBody());
}
}
I'm trying to migrate to RestAssuredMockMvc from regular MockMvc for a Spring Web Application, but I ran into a problem:
When trying to test against a simple resource, I get a 404. I wrote an equivalent MockMvc test as well, which succeeds.
Here are the two tests:
RestAssured:
package at.mycompany.iad.remote.internalorg.v1.controller;
import at.mycompany.iad.remote.internalorg.v1.resource.OrgProfileResource;
import at.mycompany.iad.remote.internalorg.v1.testconfig.TestConfig;
import io.restassured.module.mockmvc.RestAssuredMockMvc;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.context.WebApplicationContext;
import static io.restassured.RestAssured.when;
#WebAppConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = TestConfig.class)
public class OrgProfileControllerITRestAssured {
#Autowired
private WebApplicationContext context;
#Before
public void initRestAssured() {
RestAssuredMockMvc.webAppContextSetup(context);
// RestAssuredMockMvc.standaloneSetup(new OrgProfileResource(null)); //I tried this too, same result
}
#Test
public void getAd() throws Exception {
when()
.get("/examplepartnerid/profile")
.then()
.statusCode(HttpStatus.OK.value());
}
}
And MockMvc:
package at.mycompany.iad.remote.internalorg.v1.controller;
import at.mycompany.iad.remote.internalorg.v1.testconfig.TestConfig;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
#WebAppConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = TestConfig.class)
public class OrgProfileControllerITMockMvc {
#Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
#Before
public void setUp() throws Exception {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}
#Test
public void testGet() throws Exception {
MvcResult mvcResult = this.mockMvc.perform(
get("/examplepartnerid/profile"))
.andExpect(status().is(200)).andReturn();
}
}
And the controller being tested:
package at.mycompany.iad.remote.internalorg.v1.resource;
import at.mycompany.iad.remote.internalorg.v1.controller.OrgProfileController;
import at.mycompany.iad.remote.internalorg.v1.dto.OrgProfileDto;
import io.swagger.annotations.*;
import no.finntech.kernel.framework.exception.SystemException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
#RestController
#RequestMapping(value = "/{partnerId}/profile")
#Api(description = "Operations used for updating organisation services")
public class OrgProfileResource {
private final OrgProfileController controller;
#Autowired
public OrgProfileResource(OrgProfileController controller) {
this.controller = controller;
}
#RequestMapping(method = RequestMethod.GET)
#ResponseStatus(HttpStatus.OK)
#ApiOperation(value = "get organisation profile")
#ApiResponses({
#ApiResponse(code = 200, message = "returns organisation profile for supplied partnerId"),
#ApiResponse(code = 404, message = "no organisation found with supplied partnerId")
})
public ResponseEntity<OrgProfileDto> getOrgProfile(
#ApiParam(required = true) #PathVariable String partnerId
) throws SystemException {
OrgProfileDto orgProfile = controller.getOrgProfile(partnerId);
return ResponseEntity.status(HttpStatus.OK).body(orgProfile);
}
#RequestMapping(method = RequestMethod.PUT)
#ResponseStatus(HttpStatus.ACCEPTED)
#ApiOperation(value = "get organisation services")
#ApiResponses({
#ApiResponse(code = 204, message = "saved organisation services for supplied partnerId"),
#ApiResponse(code = 404, message = "no organisation found with supplied partnerId")
})
public void postOrgProfileServices(
#ApiParam(required = true) #PathVariable String partnerId,
#RequestBody OrgProfileDto requestDto
) throws SystemException {
controller.saveOrgProfile(partnerId, requestDto);
}
#RequestMapping(value = "/image", method = RequestMethod.POST, headers = "content-type=multipart/form-data", consumes = "multipart/form-data")
#ApiOperation(value = "Sets an image to existing organisation")
#ApiResponses({
#ApiResponse(code = 201, message = "The reference to the image within mycompany IAd system"),
#ApiResponse(code = 404, message = "no organisation found for given org-name")
})
#ResponseStatus(HttpStatus.CREATED)
public ResponseEntity addImageToProfile(
#ApiParam(required = true) #PathVariable String partnerId,
HttpServletRequest request) throws IOException, SystemException {
controller.saveImage(partnerId, request);
return ResponseEntity.status(202).build();
}
}
I am trying to post an xml request to a third party server and expecting an xml response back.
I am here by attaching the source code for configuring Cnfiguration,gateways & channels, Customized Rest Template class and Test Client to execute. We have various message converters for XML Posting but despite that it is always saying no suitable HTTPMessage Converters
/**** Gateway & Channel Configuration class****/
#Configuration
#MessagingGateway(name = "EntryGateway", defaultRequestChannel = "EntryChannel", defaultRequestTimeout = "2000", defaultReplyChannel = "ExitChannel", defaultReplyTimeout = "2000")
public interface Gateway {
#Gateway(requestChannel = "EntryChannel", requestTimeout = Constants.REQUEST_TIMEOUT_IN_MILLISECONDS, replyChannel = "ExitChannel", replyTimeout = Constants.RESPONSE_TIMEOUT_IN_MILLISECONDS)
ReqResMessage sendRequest(ReqResMessage request);
}
import java.util.ArrayList;
import java.util.List;
import org.aopalliance.aop.Advice;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.xml.MarshallingHttpMessageConverter;
import org.springframework.integration.annotation.IntegrationComponentScan;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.converter.MessageConverter;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
#Configuration
#ComponentScan("package_name")
#IntegrationComponentScan("package_name")
#EnableIntegration
#Import(value = ExternalSystemsConfiguration.class)
#PropertySource(value = "classpath:properties", ignoreResourceNotFound = true)
public class Configuration {
private static final Logger logger = LogbackConfig.getApplicationLogger(POPConfiguration.class);
#Autowired
Environment env;
#Autowired
ExternalSystemsConfiguration externalSystemsConfiguration;
/**
* Entry channel to the messaging system through the gateway.
*
* #return MessageChannel
*/
#Bean
public MessageChannel EntryChannel() {
return new DirectChannel();
}
#Bean
public MessageChannel RequestChannel() {
return new DirectChannel();
}
#Bean
public MessageChannel ResponseChannel() {
return new DirectChannel();
}
#Bean
public MessageChannel ExitChannel() {
return new DirectChannel();
}
#Bean
#ServiceActivator(inputChannel = "RequestChannel")
public MessageHandler cmmHttpGateway() throws Exception {
logger.debug("Entered Configuration httpGateway() ");
List<Advice> retryAdvices = new ArrayList<>();
retryAdvices.add(externalSystemsConfiguration.requestHandlerRetryAdvice());
HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler(env.getProperty("url")
);
List<HttpMessageConverter<?>> converters = new ArrayList<>();
converters.add(marshallingMessageConverter());
handler.setMessageConverters(converters);
handler.setOutputChannel(popResponseChannel());
handler.setRequiresReply(true);
//handler.setExtractPayload(true);
// handler.
handler.setHttpMethod(HttpMethod.POST);
logger.debug("Exited Configuration httpGateway() ");
return handler;
}
#Bean
public MarshallingHttpMessageConverter marshallingMessageConverter() {
return new MarshallingHttpMessageConverter(
jaxb2Marshaller(),
jaxb2Marshaller()
);
}
#Bean
public Jaxb2Marshaller jaxb2Marshaller() {
System.out.println("jaxb2Marshaller");
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setClassesToBeBound(new Class[]{
ReqResMessage.class,
ReqResBody.class,
ReqResHeader.class,
Request.class,
Response.class
});
return marshaller;
}
}
/***** Rest Template Comfiguration ******/
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import org.apache.http.Header;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthOption;
import org.apache.http.auth.AuthScheme;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.MalformedChallengeException;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.AuthenticationStrategy;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.DefaultRedirectStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.apache.http.impl.client.ProxyAuthenticationStrategy;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HttpContext;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
import org.springframework.http.converter.xml.MarshallingHttpMessageConverter;
import org.springframework.integration.handler.advice.RequestHandlerRetryAdvice;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.retry.backoff.FixedBackOffPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.web.client.RestTemplate;
#Configuration
#PropertySource(value ="classpath:integration.properties", ignoreResourceNotFound =true)
public class ExternalSystemsConfiguration {
#Autowired
Environment env;
private static final Logger logger = LogbackConfig.getApplicationLogger(ExternalSystemsConfiguration.class);
#Bean
public RequestHandlerRetryAdvice requestHandlerRetryAdvice() {
logger.debug("Entered RetryConfiguration requestHandlerRetryAdvice()");
RequestHandlerRetryAdvice retryAdvice = new RequestHandlerRetryAdvice();
RetryTemplate retryTemplate = new RetryTemplate();
FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
SimpleRetryPolicy simpleRetryPolicy = new SimpleRetryPolicy();
simpleRetryPolicy.setMaxAttempts(Integer.parseInt(env.getProperty("retryAttempts")));
fixedBackOffPolicy.setBackOffPeriod(Integer.parseInt(env.getProperty("backOffPolicy")));
retryTemplate.setBackOffPolicy(fixedBackOffPolicy);
retryTemplate.setRetryPolicy(simpleRetryPolicy);
retryAdvice.setRetryTemplate(retryTemplate);
return retryAdvice;
}
/**
* This method is used to create rest template with configurable read and connection timeouts.It is used by all http gateways.
* #return RestTemplate
*/
#SuppressWarnings("deprecation")
#Bean
public RestTemplate getRestTemplate(){
RestTemplate restTemplate = new RestTemplate();
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(new AuthScope("test.com", 443), new UsernamePasswordCredentials("testuser", "testpassword"));
HttpHost target = new HttpHost("test", 443, "https");
System.out.println("BASE64:"+credentialsProvider.toString());
// Create AuthCache instance
AuthCache authCache = new BasicAuthCache();
// Generate BASIC scheme object and add it to the local auth cache
BasicScheme basicAuth = new BasicScheme();
authCache.put(target, basicAuth);
// Add AuthCache to the execution context
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credentialsProvider);
context.setAuthCache(authCache);
Header header = new BasicHeader(HttpHeaders.CONTENT_TYPE, "application/xml");
List<Header> headers = new ArrayList<>();
headers.add(header);
HttpHost proxy = new HttpHost("", "", "http");
RequestConfig config = RequestConfig.custom()
.setProxy(proxy)
.build();
CloseableHttpClient httpClient = HttpClientBuilder.create().setProxy(proxy).setDefaultHeaders(headers).setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy())
.setDefaultCredentialsProvider(credentialsProvider).setRedirectStrategy(new DefaultRedirectStrategy() {
private String[] REDIRECT_METHODS = new String[] {
HttpGet.METHOD_NAME, HttpHead.METHOD_NAME
};
#Override
protected boolean isRedirectable(String method) {
for (String m : REDIRECT_METHODS) {
if (m.equalsIgnoreCase(method)) {
return true;
}
}
return false;
}
})
.build();
restTemplate.setRequestFactory(new Conn());
/* List<HttpMessageConverter<?>> converters = new ArrayList<>();
converters.add(marshallingMessageConverter());
converters.add(new FormHttpMessageConverter());
converters.add(new StringHttpMessageConverter());
restTemplate.setMessageConverters(converters);*/
return restTemplate;
}
public class Conn extends SimpleClientHttpRequestFactory {
public Conn(){
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("", 8080));
this.setProxy(proxy);
}
#Override
protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
// TODO Auto-generated method stub
super.prepareConnection(connection, httpMethod);
connection.setFollowRedirects(true);
String userpassword = "testuser" + ":" + "testpassword";
String encodedAuthorization = Base64.getEncoder().encodeToString(userpassword.getBytes());
System.out.println("basic-----" + encodedAuthorization);
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.addRequestProperty("Authorization", "Basic " + encodedAuthorization);
connection.addRequestProperty("content-type", "application/xml");
}
}
}
/***** Test Client to Post XML Request in the form of Java object as well as String *****/
*/
#ContextConfiguration(classes = Configuration.class)
#RunWith(SpringJUnit4ClassRunner.class)
public class Test {
private static Logger logger = LogbackConfig.getApplicationLogger(Test.class);
#Autowired
private Gateway cmmGateway;
#Autowired
RestTemplate template;
#Test
public void testJsonResponse() {
String xml = "<?xml version=\"1.0\"?>"
+"<Message>"
+ "<Header><NCPDPID>3942100</NCPDPID><SentTime>2016-07-14 06:13:00</SentTime>"
+ "<SenderID>01hw320985</SenderID><MaxRowCount>500</MaxRowCount>"
+ "</Header><Body><Request><Distance>100.00</Distance><LastName>ALLEN</LastName>"
+ "<FirstName></FirstName><Gender></Gender><Phone></Phone><City></City>"
+ "<State></State><LicensedState></LicensedState>" + "<DEA></DEA>"
+ "" + "</Request>"
+ "</Body>" + "</Message>";/*
ReqResMessage user=null;
try{
JAXBContext jaxbContext = JAXBContext.newInstance(ReqResMessage.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
InputStream is = new ByteArrayInputStream(xml.getBytes());
user= (ReqResMessage) jaxbUnmarshaller.unmarshal(is);
// System.out.println("REquest****"+user.getBody().getRequest());
}catch(Exception e){
e.printStackTrace();
}*/
ReqResMessage re = new ReqResMessage();
ReqResHeader header= new ReqResHeader();
header.setPharmacyNCPDPID("3942100");
header.setRowCount("500");
header.setSenderID("01hw320985");
Request request = new Request();
request.setDistance("100.00");
request.setLastName("ALLEN");
ReqResBody body = new ReqResBody();
body.setRequest(request);
re.setBody(body);
re.setHeader(header);
//System.out.println("Before:"+System.currentTimeMillis());
ReqResMessage response = cmmGateway.sendRequest(re);
}
}
Finally i found solution by setting header enricher out put channel to be passed as request channel to httpoutbound gateway. Find below code snippet,there i set content-type to application/xml that resolves problem.
#Bean
#Transformer(inputChannel = "RequestChannel", outputChannel = "enricherOutputChannel")
public HeaderEnricher makeEnricher() {
Map<String, ? extends HeaderValueMessageProcessor<?>> headersToAdd = Collections
.singletonMap(HttpHeaders.CONTENT_TYPE, new StaticHeaderValueMessageProcessor<>("application/xml"));
HeaderEnricher enricher = new HeaderEnricher(headersToAdd);
enricher.setDefaultOverwrite(true);
return enricher;
}