I have this webapp
Here is the controller:
#Controller
#RequestMapping(value = "/update")
public class Update{
#RequestMapping(value = "/tracking_number", method = RequestMethod.POST)
public ResponseEntity<String> updateTrackingNumber(#RequestHeader(value = "order_id")String orderId,
#RequestHeader(value = "tracking_number")String trackingNumber,
HttpSession httpSession){
//url: localhost:8080/update/tracking_number
//this one works perfectly
}
#RequestMapping(value = "/order_products", method = RequestMethod.POST)
public ResponseEntity<String> updateOrderProducts(){
return ResponseEntity.ok().body("i hope to see this text");
}
}
SpringBootApplication:
#SpringBootApplication
public class MainCore extends SpringBootServletInitializer{
public static void main(String[] args){
SpringApplication.run(MainCore.class, args);
}
}
WebApplicationInitializer:
public class AppInitializer implements WebApplicationInitializer{
#Override
public void onStartup(ServletContext container) throws ServletException{
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.scan("com.web.foo");
container.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic dispatcher = container.addServlet("mvc", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
WebMvcConfigurer:
#EnableWebMvc
#Configuration
#ComponentScan(basePackages = "com.web.foo.controller")
public class WebConfig implements WebMvcConfigurer{
#Bean
public ViewResolver internalResourceViewResolver() {
InternalResourceViewResolver bean = new InternalResourceViewResolver();
bean.setViewClass(JstlView.class);
bean.setPrefix("/WEB-INF/jsp/");
bean.setSuffix(".jsp");
return bean;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
}
The structure:
com
- web
- - foo
- - - controller
- - - - Update.java
- - - MainCore.java
- - - AppInitializer.java
- - - WebConfig.java
When I access localhost:8080/update/tracking_number it works perfect.
But when I access localhost:8080/update/order_products it no longer works and gives the response:
{
"timestamp": 1618404297125,
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/update/order_products"
}
Can you check if the request has Content-Type header. Also in #RequestMapping add consumes = "application/text" or "application/json" whatever is relevant.
Try add #ResponseBody methods of updateOrderProducts
The project is running directly from Intellij IDEA.
So, in my case, the solution was to Invalidate caches.
Related
Unable to resolve JSP page, whereas it's working fine with a simple string
Here is my folder structure of project
I am using following dep. to run an application
compile('org.apache.tomcat.embed:tomcat-embed-jasper:8.0.47')
#Configuration
#EnableWebMvc
#ComponentScan
public class SpringAppConfig extends WebMvcConfigurerAdapter implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(SpringAppConfig.class);
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(rootContext));
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
dispatcherContext.register(SpringAppConfig.class);
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher",
new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
internalResourceViewResolver.setPrefix("/WEB-INF/jsp/");
internalResourceViewResolver.setSuffix(".jsp");
return internalResourceViewResolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
#RestController
#RequestMapping("/app")
public class StudentController {
#RequestMapping("/hello") // this is working
public String sayHello() {
return "Hello from Spring 5 and embedded Tomcat 8!";
}
#RequestMapping(value = "/page", method = RequestMethod.GET)
public ModelAndView getPage() {
ModelAndView mav = new ModelAndView("welcome");
mav.addObject("firstname", "Amit");
mav.addObject("lastname", "Shah");
return mav;
}
}
getting 404 with following details when i hit http://localhost:8080/app/page
error: message /WEB-INF/jsp/welcome.jsp
description The requested resource is not available.
Tomacat
public class MyMvcApp {
private static final int PORT = 8080;
public static void main(String[] args) throws ServletException, LifecycleException {
String appBase = ".";
Tomcat tomcat = new Tomcat();
tomcat.setBaseDir(createTempDir());
tomcat.setPort(PORT);
tomcat.getHost().setAppBase(appBase);
tomcat.addWebapp("", appBase);
tomcat.start();
tomcat.getServer().await();
}
private static String createTempDir() {
try {
File tempDir = File.createTempFile("tomcat.", "." + PORT);
tempDir.delete();
tempDir.mkdir();
tempDir.deleteOnExit();
return tempDir.getAbsolutePath();
} catch (IOException ex) {
throw new RuntimeException(
"Unable to create tempDir. java.io.tmpdir is set to " + System.getProperty("java.io.tmpdir"),
ex
);
}
}
}
I'm new to spring boot and I implemented some basic REST apis using spring boot. And when I tried to call those api using react I've got an error calling some CORS policies. Then I found a solution to that problem, And all my api end point working correctly except the login api call. I get the same error calling:
Here is my web security java class.
#EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
private final UserService userDetailsService;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
public WebSecurity(UserService userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder) {
this.userDetailsService = userDetailsService;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().antMatchers(HttpMethod.POST, SecurityConstants.SIGN_UP_URL)
.permitAll().anyRequest().authenticated().and().cors().and().addFilter(getAuthenticationFilter())
.addFilter(new AuthorizationFilter(authenticationManager())).sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
public AuthenticationFilter getAuthenticationFilter() throws Exception {
final AuthenticationFilter filter = new AuthenticationFilter(authenticationManager());
filter.setFilterProcessesUrl("/users/login");
return filter;
}
}
And here is my example controller class.
#RestController
#RequestMapping("/users")
public class UserController {
#Autowired
UserService userService;
#CrossOrigin
#GetMapping(path = "/{id}",
produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE })
public UserRest getUser(#PathVariable String id) {
UserRest returnValue = new UserRest();
UserDto userDto = userService.getUserByUserId(id);
BeanUtils.copyProperties(userDto, returnValue);
return returnValue;
}
#CrossOrigin
#PostMapping(
consumes = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE },
produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE })
public UserRest createUser(#RequestBody UserDetailsRequestModel userDetails) {
UserRest returnValue = new UserRest();
UserDto userDto = new UserDto();
BeanUtils.copyProperties(userDetails, userDto);
UserDto createUser = userService.createUser(userDto);
BeanUtils.copyProperties(createUser, returnValue);
return returnValue;
}
}
I'm stuck with this problem and I really need some help. I've tried some answers given in stackoverflow as similar to my problem. But that didn't solve my problem. Mt spring boot version is 2.1.4
You are facing the issue because,you have allowed cors on your backend from port 8080, but your react is up in port 3000 on local.So , springboot will not accept the request as it is coming from a different port address.
Method 1 :
You could get away with this by using the annotation like :
#CrossOrigin(origins = "http://localhost:3000", maxAge = 3600)
Since you are using springboot , you can also use the following global config to define which all domains have access to your backend.
#Configuration
public class MyConfiguration {
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("PUT", "DELETE", "GET", "POST") //or allow all as you like
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(false).maxAge(3600);
}
};
}
}
and if you are still having issues , it might be because the spring security is not adding the CORS headers like Access-Control-Allow-Origin in your response header. In that case , you can define a custom CORS filter and add it to the spring security so that the CORS response headers are set for all spring security endpoints . You can create a filter bean like :
public class CorsFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request= (HttpServletRequest) servletRequest;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS");
response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Allow-Credentials", true);
response.setHeader("Access-Control-Max-Age", 180);
filterChain.doFilter(servletRequest, servletResponse);
}
#Override
public void destroy() {
}
}
Method 2:
since you are using spring security you could also add the CORS configuration along with spring security like :
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()
//other configurations that you want
}
#Bean
CorsConfigurationSource corsConfigurationSource()
{
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
//or any domain that you want to restrict to
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
//Add the method support as you like
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
Spring security will take up the CORS configuration even if you provide it like in method 1 as per my knowledge.But , in spring documentation they have provided this way of registering CORS with spring security as well.
In your console log that you have attached it is said that the pre flight check failed because of http status returned is not OK .So , can you try registering cors like method 2 and have a filter added so that the headers are added correctly in response. Springboot is blocking the pre flight check when the login page is accessed. You need to get your cors setup properly with the spring security to allow login page to be accessed from a dfferent port.
Confirm that your login page /login mapping have CORS allowed
Official Doc
Reference Doc
Try this,
#Configuration
public class WebConfiguration implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("*");
}
}
Update
you could also do the below,
#Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedOrigins(Collections.singletonList("*"));
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean<CorsFilter> filterRegistration = new FilterRegistrationBean<>(new CorsFilter(source));
filterRegistration.setOrder(Ordered.HIGHEST_PRECEDENCE);
return filterRegistration;
}
I want to post http://localhost:8080/TestSpringMVCAndStuff/hi/zzz?input=abcdef&crap=1234567 to a /hi/* address.
However, I keep getting 404 error.
Is there a way to make this work?
WebAppInitializer
public class WebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(WebAppConfiguration.class);
ctx.setServletContext(container);
{
ServletRegistration.Dynamic servlet = container.addServlet(
"dispatcherHi", new DispatcherServlet(ctx));
servlet.setLoadOnStartup(1);
servlet.addMapping("/hi/*");
}
}
}
AnotherController
#Controller
#RequestMapping("/hi/*")
public class AnotherController {
#Autowired(required=false)
#RequestMapping(method = RequestMethod.POST)
public void processRequest(HttpServletRequest request, HttpServletResponse response) {
try{
response.getOutputStream().write("hello world!".getBytes());
}
catch(Exception e){
e.printStackTrace();
}
}
}
WebAppConfiguration
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.test.springmvc")
public class WebAppConfiguration extends WebMvcConfigurerAdapter {
/*
* Configure View Resolver
*/
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
/*
* Configure MessageSource to provide internationalized messages
*
*/
#Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}
/*
* Configure ResourceHandlers to serve static resources like CSS/ Javascript etc...
*
*/
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
}
}
In this Context Initializer servlet mapping is /hi/* so each and every request to the server will be like http://localhost:8080/TestSpringMVCAndStuff/hi
public class WebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(WebAppConfiguration.class);
ctx.setServletContext(container);
{
ServletRegistration.Dynamic servlet = container.addServlet(
"dispatcherHi", new DispatcherServlet(ctx));
servlet.setLoadOnStartup(1);
servlet.addMapping("/hi/*");
}
}
}
so that there is no need of #RequestMapping("/hi/*") this because /hi is already appended in context path so after hi/ only need a request Mapping #RequestMapping( value="/zzz")
#Controller
#RequestMapping("/**")
public class AnotherController {
#RequestMapping(value="/zzz",method = RequestMethod.POST)
#ResponseBody
public String processRequest(HttpServletRequest request, HttpServletResponse response) {
String result="";
try{
result="hello world";
}
catch(Exception e){
e.printStackTrace();
}
return result;
}
}
inCase he change servlet Mapping like this means servlet.addMapping("/") he should Map Request for /hi in Controller and futher request also
I want to handle 404 page not found exception in my Spring MVC web app, I'm using SPRING 4.2.5.RELEASE, I had read several question regarding this topic but the similar questions are using a different spring java configuration.
I have a Global Exception Handler Controller class that have all my Exceptions, this class works fine but I can't handle a 404 page not found exception.
This is the approach that I take following a tutorial
1) I created a class named ResourceNotFoundException that extends from RuntimeException and I putted this annotation over the class definition #ResponseStatus(HttpStatus.NOT_FOUND)
like this:
#ResponseStatus(HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
}
2) I created this method in my exception's controller class
#ExceptionHandler(ResourceNotFoundException.class)
#ResponseStatus(HttpStatus.NOT_FOUND)
public String handleResourceNotFoundException() {
return "notFoundJSPPage";
}
But still when I put a URL that doesn't exist I get this error "No mapping found for HTTP request with URI"
The questions that I had read said that I need to enable to true an option for the Dispatcher but since my configuration it's different from the other questions and I don't have a Web.xml I couldn't apply that.
Here it's my Config.java
#EnableWebMvc
#Configuration
#ComponentScan({"config", "controllers"})
public class ConfigMVC extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/WEB-INF/resources/");
}
#Bean
public UrlBasedViewResolver setupViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
}
Here is my WebInitializer
public class WebInicializar implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(ConfigMVC.class);
ctx.setServletContext(servletContext);
Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
servlet.addMapping("/");
servlet.setLoadOnStartup(1);
}
}
Here is my Global Exception Handler Controller
#ControllerAdvice
public class GlobalExceptionHandlerController {
#ExceptionHandler(value = NullPointerException.class)
public String handleNullPointerException(Exception e) {
System.out.println("A null pointer exception ocurred " + e);
return "nullpointerExceptionPage";
}
#ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
#ExceptionHandler(value = Exception.class)
public String handleAllException(Exception e) {
System.out.println("A unknow Exception Ocurred: " + e);
return "unknowExceptionPage";
}
#ExceptionHandler(ResourceNotFoundException.class)
#ResponseStatus(HttpStatus.NOT_FOUND)
public String handleResourceNotFoundException() {
return "notFoundJSPPage";
}
}
And the class I created that extends Runtime Exception
#ResponseStatus(HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException{
}
I solved the problem by putting this line in my onStartup method in the WebApplicationInitializer.class
this it's the line I add servlet.setInitParameter("throwExceptionIfNoHandlerFound", "true");
this is how it looks the complete method with the new line I added
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(ConfigMVC.class);
ctx.setServletContext(servletContext);
Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
servlet.addMapping("/");
servlet.setLoadOnStartup(1);
servlet.setInitParameter("throwExceptionIfNoHandlerFound", "true");
}
Then I created this controller method in my GlobalExceptionHandlerController.class
#ExceptionHandler(NoHandlerFoundException.class)
#ResponseStatus(HttpStatus.NOT_FOUND)
public String handle(NoHandlerFoundException ex) {
return "my404Page";
}
and that solved my problem I deleted the handleResourceNotFoundException controller method in my GlobalExceptionHandlerController.class since it wasn't necessary and also I deleted the exception class ResourceNotFoundException.class that I created
You can also extend AbstractAnnotationConfigDispatcherServletInitializer and override this method:
#Override
protected DispatcherServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
final DispatcherServlet dispatcherServlet = (DispatcherServlet) super.createDispatcherServlet(servletAppContext);
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
return dispatcherServlet;
}
OR this one:
#Override
public void customizeRegistration(ServletRegistration.Dynamic registration) {
registration.setInitParameter("throwExceptionIfNoHandlerFound", "true");
}
And finally in your ControlerAdvice use this:
#ExceptionHandler(NoHandlerFoundException.class)
public String error404(Exception ex) {
return new ModelAndView("404");
}
Add following code in any controller and create a 404 page
#GetMapping("/*")
public String handle() {
return "404";
}
I found that the answer by zygimantus didnt work for some reason, so if you also have the same problem , then instead of declaring an "#ExceptionHandler", add one of these to a "#Configuration" class instead. I put mine in my WebMvcConfigurerAdapter
#Bean
public HandlerExceptionResolver handlerExceptionResolver(){
HandlerExceptionResolver myResolver = new HandlerExceptionResolver(){
#Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) {
//return your 404 page
ModelAndView mav = new ModelAndView("404page");
mav.addObject("error", exception);
return mav;
}
};
return myResolver;
}
But make sure you also follow the rest of zygimantus ie
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
This question already has answers here:
Why does Spring MVC respond with a 404 and report "No mapping found for HTTP request with URI [...] in DispatcherServlet"?
(13 answers)
Closed 6 years ago.
I declared UrlBasedViewResolver method in RestAppConfig to render jsp page.
#Bean
public UrlBasedViewResolver urlBasedViewResolver(){
UrlBasedViewResolver res = new InternalResourceViewResolver(); //new UrlBasedViewResolver();//
res.setOrder(10);
res.setViewClass(JstlView.class);
res.setPrefix("/views/templates/");
res.setSuffix(".jsp");
return res;
}
and delclared ModelAndView method in controller BaseController
#Configuration
#EnableWebMvc
#ComponentScan(basePackages={"kr.co.cdefi.base.restapp.controller"}
, useDefaultFilters=false
, includeFilters={#Filter(Controller.class)
, #Filter(ControllerAdvice.class)})
public class RestAppConfig extends WebMvcConfigurerAdapter{
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer
.useJaf(true)
.favorPathExtension(true)
.favorParameter(false)
.ignoreAcceptHeader(false)
.defaultContentType(MediaType.APPLICATION_JSON)
.mediaType("json", MediaType.APPLICATION_JSON)
.mediaType("xml", MediaType.APPLICATION_XML);
};
#Bean
public UrlBasedViewResolver urlBasedViewResolver(){
UrlBasedViewResolver res = new InternalResourceViewResolver(); //new UrlBasedViewResolver();//
res.setOrder(10);
res.setViewClass(JstlView.class);
res.setPrefix("/views/templates/");
res.setSuffix(".jsp");
return res;
}
}
finally, I run tomcat8 server using Eclipse.
But requested URI /home just responses this.
WARN o.s.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/TheBigs/views/templates/index.jsp] in DispatcherServlet with name 'rest-app'
I opened deployment location
...\org.eclipse.wst.server.core\tmp1\wtpwebapps\TheBigs\views\templates\
... files exists. What is the problem? Is there anything I missing?
I added my controller code BaseController
#Controller
public class BaseController {
Logger logger = LoggerFactory.getLogger(BaseController.class);
#Autowired UserService userService;
#RequestMapping(value="/home", method = RequestMethod.GET)
public ModelAndView home(){
logger.debug("home!");
ModelAndView view = new ModelAndView();
view.setViewName("index");
return view;
}
#RequestMapping(value="/", method = RequestMethod.GET)
public String index(Model model){
logger.debug("index page!");
model.addAttribute("message", "success");
return "test";
}
}
There images are jsp files directory, and Web Deployment Assembly defined.
Solved. It caused by servlet-mapping.
I changed url-pattern set to / from /*, then works.