I'm Implementing a geoserver's OWS. I want to a specific method of the OWS get a ModelAndView as following:
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
public class HelloWorld {
public HelloWorld() {
// Do nothing
}
public ModelAndView sayHello(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException, Exception {
ModelAndView m = new ModelAndView("index");
return m;
}
}
How can I do this?
Related
NOTE: the errors below were actually caused by a typo in the filter, see #jccampanero mentions in his answer below
I've been trying a couple different approaches to testing a Filter however I'm continuously getting one error or another so I'm hoping for some direction.
Here's a dummy Filter that should just do a redirect.
package org.example.filters;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
#Component
public class RedirectFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) req;
chain.sendRedirect("/splash");
}
}
And a basic Spring Boot Application class:
package org.example;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class ApplicationClass {
}
I think I'm just not clear on what 'level' of Spring Boot Test I'm trying to do, here's some attempts I've done and the errors:
Option 1. Trying with mocks, for example from here
package org.example.filters;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
import org.junit.jupiter.api.Test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
public class LocaleFilterIntegrationTestStandalone {
#Test
public void whenNoLocaleRedirectToSplash() throws Exception {
standaloneSetup(new TestController()).addFilters(new RedirectFilter()).build().perform(get("/"))
.andExpect(status().isFound()).andExpect(redirectedUrl("/splash"));
}
#Controller
private static class TestController {
#GetMapping("/")
public String get() {
return "got it";
}
}
}
Error: java.lang.ClassCastException: class org.springframework.mock.web.MockHttpServletRequest cannot be cast to class javax.servlet.http.HttpServletResponse
Option 2, try using #WebMvcTest, which has the same issue as Option 1
package org.example.filters;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.stereotype.Controller;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.bind.annotation.GetMapping;
#WebMvcTest
public class LocaleFilterIntegrationTestWebMvc {
#Autowired
private MockMvc mvc;
#Test
public void noLanguageShouldRedirectToSplash() throws Exception {
mvc.perform(get("/")).andExpect(status().isFound()).andExpect(redirectedUrl("/splash"));
}
#Controller
private static class TestController {
#GetMapping("/")
public String get() {
return "got it";
}
}
}
Error: java.lang.ClassCastException: class org.springframework.mock.web.MockHttpServletRequest cannot be cast to class javax.servlet.http.HttpServletResponse
Option 3, try booting the whole context, which I think is required to be able to cast to HttpServletRequest:
package org.example.filters;
import java.net.URI;
import org.junit.jupiter.api.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.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class LocaleFilterIntegrationTest {
#LocalServerPort
private int port;
#Autowired
private TestRestTemplate restTemplate;
#Test
public void noLanguageShouldRedirectToSplash() throws Exception {
URI uri = new URI("http", "localhost:" + port, "/", null, null);
String result = restTemplate.getForObject(uri.toString(), String.class);
// not sure how, but test for redirect...
}
#Controller
private static class TestController {
#GetMapping("/")
public String get() {
return "got it";
}
}
}
Error: class org.apache.catalina.connector.RequestFacade cannot be cast to class javax.servlet.http.HttpServletResponse
Option 4, suggested by #m-deinem
package org.example.filters;
import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
public class LocaleFilterIntegrationTestPlain {
private final RedirectFilter redirectFilter = new RedirectFilter();
#Test
public void noLanguageShouldRedirectToSplash() throws Exception {
MockHttpServletRequest req = new MockHttpServletRequest();
MockHttpServletResponse res = new MockHttpServletResponse();
MockFilterChain chain = new MockFilterChain();
redirectFilter.doFilter(req, res, chain);
}
}
Error: java.lang.ClassCastException: class org.springframework.mock.web.MockHttpServletRequest cannot be cast to class javax.servlet.http.HttpServletResponse
First your RedirectFilter contains an error it tries to cast the incoming HttpServletRequest to a HttpServletResponse as you are using the wrong variable.
#Component
public class RedirectFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
res.sendRedirect("/splash");
}
}
Both lines use req whereas the latter should use res (which is also what the exception is quite literally telling you).
Next just write a simple unit test, you are making things overly complex by trying to write integration tests.
public class RedirectFilterTest
private final RedirectFilter filter = new RedirectFilter();
#Test
public void redirectTest() {
MockHttpServletRequest req = new MockHttpServletRequest();
MockHttpServletResponse res = new MockHttpServletResponse();
MockFilterChain chain = new MockFilterChain();
filter.doFilter(req, res, chain);
assertEquals("/splash", res.getRedirectedUrl());
}
Please, maybe it is just a typo, but be aware that in your RedirectFilter doFilter method you are incorrectly casting the variable req to HttpServletResponse:
package org.example.filters;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
#Component
public class RedirectFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
// Please, note the incorrect cast
HttpServletResponse response = (HttpServletResponse) req;
chain.sendRedirect("/splash");
}
}
Instead, it should be:
package org.example.filters;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
#Component
public class RedirectFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
chain.sendRedirect("/splash");
}
}
It can be very likely the reason of the ClassCastException and the failing tests.
Once solved, the solution proposed by #M. Deinum is a very good and straightforward one.
I'm am trying to set up an application that has an Angular front-end and a Maven/Spring Boot backend and have set up my first REST controller. My issue is that when I send a GET HTTP request to the backend from my Angular IDE it returns an error stating:
"Access to XMLHttpRequest at 'http://localhost:8080/api/getData' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource."
I'm confused as I have set up the "doFilter" to accept all requests from any origin so it shouldn't be throwing this error. My code follows:
My APIController:
package com.SSCCoursework.controller;
import com.SSCCoursework.Model.SharePrice;
import com.SSCCoursework.Model.Shares;
import com.SSCCoursework.Model.SharesList;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#CrossOrigin (origins = "http://localhost:4200", maxAge = 3600)
#RestController
public class ApiController
{
File Shares_File = new File("Shares_Data.xml");
ArrayList<Shares> shareList = new ArrayList<Shares>();
#RequestMapping(value="/api/getData", produces="application/JSON")
public Object getData()
{
Shares share1 = new Shares();
SharePrice share1_2 = new SharePrice();
share1.setCompanyName("test");
share1.setCompanySymbol("test");
share1.setNumOfShares(123);
Date date = new Date();
share1.setLastShareUpdate(date);
share1_2.setCurrency("dollar");
share1_2.setValue(12345f);
share1.setSharePrice(share1_2);
shareList.add(share1);
SharesList sharelist = new SharesList();
sharelist.setBookList(shareList);
return share1;
}
}
My SimpleCORSFilter:
package com.SSCCoursework.Security;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
#Component
public class SimpleCORSFilter implements Filter
{
#Override
public void init(FilterConfig filterConfig) throws ServletException
{
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException
{
HttpServletResponse res = (HttpServletResponse) response;
HttpServletRequest req = (HttpServletRequest) request;
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS");
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Accept-Encoding, Accept-Language, Host, Referer, Connection, User-Agent, authorization, sw-useragent, sw-version");
if (req.getMethod().equals("OPTIONS"))
{
res.setStatus(HttpServletResponse.SC_OK);
return;
}
filterChain.doFilter(request, response);
}
#Override
public void destroy()
{
}
}
My Angular code is just trying to use a GET method (this.httpClient.get('http://localhost:8080/api/getData') to print the data to the browser console but the error is preventing it from working. Am I missing a step in my backend?
you can easily define a global cors config just by adding in your main application class where you start your spring boot app
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("http://localhost:8080")
.allowedMethods("PUT", "DELETE", "GET", "POST");
}
};
}
for more details take a look here
I have a mvc web application which need to be secured using the java filter concept.
If I am not logged in the application should take me to the login page and if I am logged in the application must not allow me to access the login page.
Below is the filter code which I have implementd in filter
Login url is /login (login.jsp)
home page url is /home (home.jsp)
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
#WebFilter("/LoginFilter")
public class LoginFilter implements Filter {
private RequestDispatcher dispatcher;
public LoginFilter() {
}
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req=(HttpServletRequest) request;
HttpServletResponse res=(HttpServletResponse) response;
HttpSession session=req.getSession(false);
String reqUri=req.getRequestURI();
System.out.println("RequestURI:"+reqUri);
if(session!=null && session.getAttribute("user")!=null){
if(reqUri.equals("login")){
System.out.println("you are already logged in");
dispatcher=request.getRequestDispatcher("/home");
dispatcher.forward(req, res);
return;
}
else{
chain.doFilter(request, response);
}
}
}
public void init(FilterConfig fConfig) throws ServletException {
}
}
You can use the below updated code to check if it is completing your requirement or not.
where login url is predefined and checking every time for logged-in user to take him/her to secured page.
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
#WebFilter("/LoginFilter")
public class LoginFilter implements Filter {
private String loginUri="/LoginLogout/login";
private RequestDispatcher dispatcher;
public LoginFilter() {
}
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req=(HttpServletRequest) request;
HttpServletResponse res=(HttpServletResponse) response;
HttpSession session=req.getSession(false);
String reqUri=req.getRequestURI();
System.out.println("RequestURI:"+reqUri);
//already looged in
if(session!=null && session.getAttribute("user")!=null){
//trying to access login url after logged in
if(reqUri.equals(loginUri)){
System.out.println("you are already logged in");
dispatcher=request.getRequestDispatcher("/home");
dispatcher.forward(req, res);
return;
}
else{
chain.doFilter(request, response);
}
}
//if not logged-in
else{
System.out.println("First have to logged in");
dispatcher=request.getRequestDispatcher("/login");
dispatcher.forward(req, res);
return;
}
}
public void init(FilterConfig fConfig) throws ServletException {
}
}
Is there any reason why a filter slow down the server response?
I've a web app with the following filter:
package com.bingo.filters;
import java.io.IOException;
import java.util.Arrays;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
public class CacheFilter implements Filter {
static class CacheControlHeaderResponse extends HttpServletResponseWrapper {
public static final String[] CACHEABLE_CONTENT_TYPES = new String[] {
"text/css", "text/javascript", "image/png", "image/jpeg",
"image/gif", "image/jpg" };
static {
Arrays.sort(CACHEABLE_CONTENT_TYPES);
}
public CacheControlHeaderResponse(HttpServletResponse response) {
super(response);
}
#Override
public void setContentType(String contentType) {
super.setHeader("Expires", "-1");
super.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
super.setHeader("Pragma", "no-cache");
super.setContentType(contentType);
}
}
public CacheFilter() {
}
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
chain.doFilter(request, new CacheControlHeaderResponse(res));
}
public void init(FilterConfig fConfig) throws ServletException {
}
}
This is the configuration I added to my web.xml
<filter>
<filter-name>cFilter</filter-name>
<filter-class>com.bingo.filters.CacheFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cFilter</filter-name>
<url-pattern>/bingo/*</url-pattern>
</filter-mapping>
When I deploy the war with this new code, the application server answer very slowly. It takes 6 or 7 seconds for a page to be retrieved.
But if I deploy the old war file without the above code, then the response is very fast.
Is there anything wrong into the above code, that can explain the performance issue?
As mentioned in Restlet docs it has feature called "tunneling". Does this feature exist in RESTEasy too?
Servlet below supports "tunneling" by delegating "method" parameter from request.
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher;
public class TunnelingDispatcher extends HttpServletDispatcher {
#Override
protected void service(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) throws ServletException,
IOException {
String method = httpServletRequest.getParameter("method");
if (method == null) {
method = httpServletRequest.getMethod();
} else {
method = method.toUpperCase();
}
service(method, httpServletRequest, httpServletResponse);
}
}