I have seen everywhere in the Spring MVC examples on net that we can use HttpServlet request & response objects in the method parameter in the controller. But when I am using it. Given in the below code.
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class StudentController {
public void testSyntax(HttpServletRequest request, HttpServletResponse response)
{
System.out.println("Inside testSyntax");
}
}
The compiler is throwing an error. HttpServletRequest request cannot be resolved to a type.
I am using Spring MVC 3.0. Can anyone tell me the reason for it.
You are missing a couple of import statements.
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
Where you get these classes from typically is different per application container you use. My favorite example is Tomcat:
<tomcat_base_dir>/lib/servlet-api.jar
Related
I want to test my spring boot application using TestRestemplate, however I am unable to test get url, what I am trying to do here is I am injecting some predefine objects setting into list and mocking find all method.
below is my test code looks like.
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.junit.Before;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#ActiveProfiles("test")
public class PersonControllerTests {
#Autowired
private TestRestTemplate restTemplate;
#MockBean
private PersonRepository mockRepository;
#Before
public void init() {
List<Person> list = new ArrayList<>();
Person p1 = new Person("dumm1", "lastName1",22);
Person p2 = new Person("dumm2", "lastName2",32);
p1.setId(1l);
list.add(p2);
list.add(p1);
when(mockRepository.findAll()).thenReturn(list);
}
#Test
public void getPersonsGoodReq() throws Exception {
ResponseEntity<Person[]> response = restTemplate
.withBasicAuth("admin", "password")
.getForEntity("/persons/all", Person[].class);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertEquals(response.getBody().length, 2);
}
}
I am expecting answer to be 2, but when I am seeing body response it is empty array.
what might have gone wrong I am unable to get
As you're using JUnit Jupiter, you have to use #BeforeEach. #Before is from JUnit 4 and hence wasn't invoked as part of the test's lifecycle:
#BeforeEach
public void init() {
List<Person> list = new ArrayList<>();
Person p1 = new Person("dumm1", "lastName1",22);
Person p2 = new Person("dumm2", "lastName2",32);
p1.setId(1l);
list.add(p2);
list.add(p1);
when(mockRepository.findAll()).thenReturn(list);
}
I'm using Spring's ProxyExchange, and I want to change the default RestTemplate (in order to ignore certificates on dev env).
Is there a way to do that?
Using MVC (and not flux)
We altered RestTemplate using ProxyExchangeArgumentResolver class. below is code snippet
package com.vikrant.practice.config;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.gateway.mvc.config.ProxyExchangeArgumentResolver;
import org.springframework.cloud.gateway.mvc.config.ProxyProperties;
import org.springframework.cloud.gateway.mvc.config.ProxyResponseAutoConfiguration;
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.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import java.util.Optional;
#Configuration
#EnableAutoConfiguration
#ComponentScan(basePackages = {"com.vikrant.practice"})
public class XyzConfig {
public RestTemplate restTemplate() {
RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(30000).setConnectTimeout(30000).build();
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager();
poolingHttpClientConnectionManager.setMaxTotal(100);
poolingHttpClientConnectionManager.setDefaultMaxPerRoute(100);
HttpClient httpClient = HttpClientBuilder
.create().setDefaultRequestConfig(requestConfig)
.setConnectionManager(poolingHttpClientConnectionManager)
.disableCookieManagement().build();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setConnectionRequestTimeout(1000);
factory.setReadTimeout(30000);
factory.setConnectTimeout(30000);
factory.setHttpClient(httpClient);
RestTemplate restTemplate = new RestTemplate(factory);
return restTemplate;
}
#Bean
public ProxyExchangeArgumentResolver proxyExchangeArgumentResolver(
Optional<RestTemplateBuilder> optional, ProxyProperties proxy) {
RestTemplate template = restTemplate();
template.getMessageConverters().add(new ByteArrayHttpMessageConverter() {
#Override
public boolean supports(Class<?> clazz) {
return true;
}
});
ProxyExchangeArgumentResolver resolver = new ProxyExchangeArgumentResolver(template);
resolver.setHeaders(proxy.convertHeaders());
resolver.setSensitive(proxy.getSensitive());
return resolver;
}
}
This was done for SpringBoot application. In case you want to use it in web application then create a class extending SpringBootServletInitializer and implementing WebApplicationInitializer and in that under configure method wire this class.
So basically I built a RestTemplateCustomizer and added a bean to customize the default RestTemplate
I'm looking for a way to register a javax.servlet.http.HttpServlet in ktor, but can't find any.
Do I need to install a feature? Register it in Routing? Can I enable scanning of #WebServlet annotations?
Example servlet:
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet("/foo")
public class MyServlet extends HttpServlet {
#Override
protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) {
// ...
}
}
What you want is currently not supported by design. See my Feature Request and corresponding PR to add support for it.
I have a controller protected with HTTP Basic authentication.
I setup the app to use session cookies and it works.
However when I test the controller using MockMvc, a successful authentication does not give me any cookie.
Web configuration:
package world.pyb.spring.cookiesdemo;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
#Configuration
#EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("argentina").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
//#formatter:off
http.httpBasic()
.and().authorizeRequests().antMatchers(HttpMethod.GET, "/hello").authenticated()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
//#formatter:on
}
}
Simple controller:
package world.pyb.spring.cookiesdemo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class HelloController {
#RequestMapping("/hello")
public String index() {
return "Greetings from Spring Boot!";
}
}
Simple controller test that doesn't give me the session cookie:
package world.pyb.spring.cookiesdemo;
import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class HelloControllerTest {
#Autowired
private MockMvc mvc;
#Test
public void getHello() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/hello")
.with(SecurityMockMvcRequestPostProcessors.httpBasic("admin", "argentina"))
)
// prints "Cookies = []"
.andDo(MockMvcResultHandlers.print())
.andExpect(cookie().exists("JSESSIONID"))
.andExpect(status().is2xxSuccessful())
.andExpect(content().string(equalTo("Greetings from Spring Boot!")));
}
}
Related questions:
Why does Spring MockMvc result not contain a cookie?
Unit Testing /login in Spring MVC using MockMvc
Spring MVC testing (security Integration test), JSESSIONID is not present
Some answers suggest not to use MockMvc but I'd like to keep using it if possible.
As shown in the question's code, MockMvcResultMatcher includes support for cookies.
This will work fine, as long as the controller under test itself delivers the cookie. The problem here is that the cookie is delivered by Spring Security, which is a wrapper around your controller. MockMvc is testing your controller directly, and not testing your controller running in its real HTTP server, as would be required to test the security-layer cookies.
That's why TestRestTemplate, which invokes your controller in its full server context, delivers a more thorough test environment.
Notice however that as of Spring 5, the newer approach to running-server API testing is based on WebTestClient.
I developed a Spring MVC webapp with rest methods. I would love to use RestAssured to create JUnit test classes. From the documentation it looks really simple to do but I'm having some problem instead. Basically I want to use it to avoid a runtime Tomcat instance but the problem is that when I execute the JUnit test class I obtain the following exception:
org.apache.http.conn.HttpHostConnectException: Connection to http://localhost:8082 refused
...
Caused by: java.net.ConnectException: Connection refused
This is my JUnit class:
import static com.jayway.restassured.RestAssured.given;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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 com.jayway.restassured.module.mockmvc.RestAssuredMockMvc;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"file:src/test/resources/spring/application-test-config.xml"})
#WebAppConfiguration
public class ExternalControllerTest {
private static final Logger logger = LoggerFactory.getLogger(ExternalControllerTest.class);
#Autowired
WebApplicationContext webApplicationContext;
#Before
public void setUp() throws Exception {
RestAssuredMockMvc.webAppContextSetup(webApplicationContext);
}
#Test
public void addClientDeviceId_Success() {
given().get("/api/test").then().statusCode(200);
}
}
I also tried to configure RestAssuredMockMvc directly with the controller class but the result is the same:
RestAssuredMockMvc.standaloneSetup(new ExternalController());
The controller looks like that:
#Controller
#RequestMapping("/api")
public class ExternalController {
public ExternalController() {
logger.info("ExternalController initialised!");
}
#RequestMapping(value="/test", method = RequestMethod.GET, produces={"application/json", "application/xml"})
public #ResponseBody DmsResponse test(HttpServletResponse response) {
response.setStatus(HttpServletResponse.SC_OK);
return null;
}
}
In this guide http://www.jayway.com/2014/01/14/unit-testing-spring-mvc-controllers-with-rest-assured/ is specified that "The most important aspect is that it’s simpler to get the environment started. You don’t need to bootstrap a container (for example Jetty or Tomcat), you simply initialize RestAssuredMockMvc with a context (for example a controller) and you’re ready to go." So I don't understand where the problem is. Any suggestion?
The war file deployed with Tomcat works fine.
Thanks
You are statically importing the wrong methods. You're importing given from com.jayway.restassured.RestAssured (io.restassured.RestAssured if using version 3.x) but you should statically import the methods from com.jayway.restassured.module.mockmvc.RestAssuredMockMvc (io.restassured.module.mockmvc.RestAssuredMockMvc in version 3.x). Refer to the documentation for more info.