SpringBoot Swagger2 rest API documentation is not loading - java

I am just trying out to get the documentation for my small REST API written in in spring with swagger2 inclusion. When i try to access my swagger page the following error is shown in browser console.
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Mon Sep 25 21:09:08 IST 2017
There was an unexpected error (type=Not Found, status=404).
No message available
My code snippets are below mentioned.
package com.example.demo;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
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.bind.annotation.RestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
#RestController
#RequestMapping(value="/rooms")
#Api(value="rooms", tags=("rooms"))
public class RoomController {
#Autowired
private RoomRepositery roomRepo;
#RequestMapping(method = RequestMethod.GET)
#ApiOperation(value="Get All Rooms", notes="Get all rooms in the system", nickname="getRooms")
public List<Room> findAll(#RequestParam(name="roomNumber", required=false)String roomNumber){
if(StringUtils.isNotEmpty(roomNumber)) {
return Collections.singletonList(roomRepo.findByRoomNumber(roomNumber));
}
return (List<Room>) this.roomRepo.findAll();
}
}
App class
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import static springfox.documentation.builders.PathSelectors.any;
#SpringBootApplication
#EnableSwagger2
public class RoomServiceApp {
#Bean
public Docket api(){
return new Docket(DocumentationType.SWAGGER_2).groupName("Room").select()
.apis(RequestHandlerSelectors.basePackage("com.example.demo"))
.paths(any()).build().apiInfo(new ApiInfo("Room Services",
"A set of services to provide data access to rooms", "1.0.0", null,
new Contact("Frank Moley", "https://twitter.com/fpmoles", null),null, null));
}
public static void main(String[] args) {
SpringApplication.run(RoomServiceApp.class, args);
}
}
I am not able to found what i am missing here. Can any one help me out?
Thanks

You have to use http://localhost:9090/swagger-ui.html for swagger UI and http://localhost:9090/v2/api-docs?group=Room for JSON API.
I used the same code and find attached screenshot.
refer to this project for more details.

Request mapping at method level should have URI path like below for findAll method. Consumes and produces also required if there is input passed to method and output returned from method.
The reason is empty mapping value at method level will result in 'host:port/contextPath/' for which swagger will return 404.
#RequestMapping(method = { RequestMethod.GET }, value = "/roomList", consumes = {
MediaType.ALL}, produces = { MediaType.ALL})

Related

Login problems: Authentication autowired controller issue Apache Netbeans Java

I'm constructing a Login with java, I've been following a tutorial but now I've encountered an issue. The app is supposed to be working and I should be able to try it on postman, but it is failing to start.
The issue is:
Description:
Field passwordEncoder in com.portfolio.anamorujaportfolio.Security.Controller.AuthController required a bean of type 'org.springframework.security.crypto.password.PasswordEncoder' that could
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'org.springframework.security.crypto.password.PasswordEncoder' in your configuration.
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package com.portfolio.anamorujaportfolio.Security.Controller;
import com.portfolio.anamorujaportfolio.Security.Dto.JwtDto;
import com.portfolio.anamorujaportfolio.Security.Dto.LoginUsuario;
import com.portfolio.anamorujaportfolio.Security.Dto.NuevoUsuario;
import com.portfolio.anamorujaportfolio.Security.Entity.Rol;
import com.portfolio.anamorujaportfolio.Security.Entity.Usuario;
import com.portfolio.anamorujaportfolio.Security.Enums.RolNombre;
import com.portfolio.anamorujaportfolio.Security.Service.RolService;
import com.portfolio.anamorujaportfolio.Security.Service.UsuarioService;
import com.portfolio.anamorujaportfolio.Security.jwt.JwtProvider;
import java.util.HashSet;
import java.util.Set;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping("/auth")
#CrossOrigin
public class AuthController {
#Autowired
PasswordEncoder passwordEncoder;
#Autowired
AuthenticationManager authenticationManager;
#Autowired
UsuarioService usuarioService;
#Autowired
RolService rolService;
#Autowired
JwtProvider jwtProvider;
#PostMapping("/nuevo")
public ResponseEntity<?> nuevo(#Valid #RequestBody NuevoUsuario nuevoUsuario, BindingResult bindingResult){
if(bindingResult.hasErrors())
return new ResponseEntity(new Mensaje("Campos mal puestos o email invalido"), HttpStatus.BAD_REQUEST);
if(usuarioService.existsByNombreUsuario(nuevoUsuario.getNombreUsuario()))
return new ResponseEntity(new Mensaje("Ese nombre de usuario ya existe"), HttpStatus.BAD_REQUEST);
if(usuarioService.existsByEmail(nuevoUsuario.getEmail()))
return new ResponseEntity(new Mensaje("Ese email ya existe"), HttpStatus.BAD_REQUEST);
Usuario usuario = new Usuario(nuevoUsuario.getNombre(), nuevoUsuario.getNombreUsuario(), nuevoUsuario.getEmail(), passwordEncoder.encode(nuevoUsuario.getPassword()));
Set<Rol>roles=new HashSet<>();
roles.add(rolService.getByRolNombre(RolNombre.ROLE_USER).get());
if(nuevoUsuario.getRoles().contains("admin"))
roles.add(rolService.getByRolNombre(RolNombre.ROLE_ADMIN).get());
usuario.setRoles(roles);
usuarioService.save(usuario);
return new ResponseEntity(new Mensaje("Usuario guardado"), HttpStatus.CREATED);
}
#PostMapping("/login")
public ResponseEntity<JwtDto> login(#Valid #RequestBody LoginUsuario loginUsuario, BindingResult bindingResult){
if(bindingResult.hasErrors())
return new ResponseEntity(new Mensaje("Campos mal puestos"), HttpStatus.BAD_REQUEST);
Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginUsuario.getNombreUsuario(),loginUsuario.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = jwtProvider.generateToken(authentication);
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
JwtDto jwtDto = new JwtDto(jwt, userDetails.getUsername(), userDetails.getAuthorities());
return new ResponseEntity(jwtDto, HttpStatus.OK);
}
}
It's my first go at Java, thanks in advance for the help!!
I've no idea, but I want it to run
The error says it all. Basically the application thinks that a configuration is missing which is unable to bind the PasswordEncoder.
Upon closer look, PasswordEncoder is part of the Spring package and the way AutoInjections work is (by default), spring only scans the classes from the root package and since its not part of the root it cant autowire the bean.
You can initialise it like this from a custom config class and annotate it as a Bean and then Autowire it..
#Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
Please refer an implementation here
https://www.baeldung.com/spring-security-registration-password-encoding-bcrypt
Please refer to the documentation here
https://docs.spring.io/spring-security/reference/features/authentication/password-storage.html#authentication-password-storage
Hope this helps!

Spring boot , i18n error, wrong implementation of LocaleResolver is choosen

I am developing a spring boot based application that supports internationalisation
My env:
Jdk11
Spring boot 2.7.0
Spring Security
Here is my web mvc conf
WebMvcConf.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import java.util.Locale;
#Configuration
public class WebMvcConf implements WebMvcConfigurer {
public static final Locale idnLocale = Locale.forLanguageTag("id-ID");
#Bean
public LocaleResolver defaultLocaleResolver(){
var resolver = new SessionLocaleResolver();
resolver.setDefaultLocale(idnLocale);
return resolver;
}
#Bean
public LocaleChangeInterceptor localeChangeInterceptor(){
var interceptor = new LocaleChangeInterceptor();
interceptor.setIgnoreInvalidLocale(false);
interceptor.setParamName("lang");
return interceptor;
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
}
And here is my security config:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.header.HeaderWriterFilter;
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestWrapper;
#Configuration
#EnableWebSecurity
public class SecurityConf{
#Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.cors()//enable cors
.and()
.csrf().disable()//disable csrf
.sessionManagement(session->session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))//stateless session (Rest)
.authorizeHttpRequests(authz->authz
.antMatchers(HttpMethod.GET,"/").permitAll()
.antMatchers(HttpMethod.POST,"/users/login","users/register","users/forgot-password").permitAll()
.antMatchers(HttpMethod.PATCH,"/users/password").permitAll()
.anyRequest().authenticated());//authorize any request except ignored endpoint above
return httpSecurity.build();
}
}
Here is the structure of the message properties:
Here is my application.yml content:
Here is the content of messages_en.properties:
rest.welcome.ok=Welcome to ABC Backend Service, have fun!!!
rest.users.login.ok=Successfully Logged in
#Error Message
rest.500.err=Internal Server Error
rest.422.err=Constraint Violation Error
rest.400.err=Invalid request body
rest.required-req-body-missing.err=Required request body is missing
Here is content of messages.properties:
rest.welcome.ok=Selamat Datang di Service ABC, selamat bersenang-senang!!!
rest.users.login.ok=Login sukses
#Error message
rest.500.err=Kesalahan Internal di sistem
rest.422.err=Error pelanggaran constraint
rest.400.err=Kesalahan pada request body
rest.required-req-body-missing.err=Request body (payload) yang dibutuhkan tidak ditemukan
Here is my test to test the message source:
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.MessageSource;
import java.util.Locale;
#SpringBootTest
public class MessageSourceTest {
#Autowired
private MessageSource messageSource;
#BeforeEach
void init(){
}
#Test
public void message_provided_should_correctly_localized(){
String msgEnglish = messageSource.getMessage("rest.500.err",null, new Locale("en"));
String msgIndo = messageSource.getMessage("rest.500.err",null,Locale.forLanguageTag("id-ID"));
Assertions.assertEquals("Internal Server Error",msgEnglish);
Assertions.assertEquals("Kesalahan Internal di sistem",msgIndo);
}
}
And the test is pass:
But when I try to hit a mvc rest controller and add query parameter lang=en , I always got an error response saying Cannot change HTTP accept header - use a different locale resolution strategy
So I debug the LocaleChangeInterceptor and found that spring boot provide a wrong implementation of the LocaleResolver, they provide AcceptHeaderResolver, which what I want is the SessionLocaleResolver as I state it in my WebMvcConf class. See following picture:
Anyone knows what is wrong and how to fix it?any response will be appreciated

How to use MockMvc and MockRestServiceServer in Java #SpringBootTest

I am attempting to write a #SpringBootTest which will both issue REST requests and mock responses. I want to do this because my spring application receives REST requests and in response it fetches information from another source using REST. I would like to trigger my application by initiating a REST GET (MockMvc), but would also like to mock the other source's response (MockRestServiceServer).
Here is a sanitized version of the test, with my application removed:
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
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.boot.test.context.TestConfiguration;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.client.RestTemplate;
import static org.hamcrest.Matchers.containsString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
#Slf4j
#ExtendWith(SpringExtension.class)
#SpringBootTest
#AutoConfigureMockMvc
class RestTest {
private static final String URI = "/my-test-uri";
private static final String RESPONSE = "my-response";
#Autowired
private MockMvc mockMvc;
#Test
void testRest() throws Exception {
log.info("Initiating request for GET {}", URI);
mockMvc.perform(get(URI))
.andExpect(status().isOk())
.andExpect(content().string(containsString(RESPONSE)));
}
#TestConfiguration
static class TestConfig {
#Primary
#Bean
public RestTemplateBuilder restTemplateBuilder() {
RestTemplate restTemplate = new RestTemplate();
MockRestServiceServer server = MockRestServiceServer.createServer(restTemplate);
server.expect(requestTo(URI))
.andRespond(withSuccess(RESPONSE, MediaType.APPLICATION_JSON));
log.info("Mocking response to GET {}: {}", URI, RESPONSE);
RestTemplateBuilder mockBuilder = mock(RestTemplateBuilder.class);
when(mockBuilder.build()).thenReturn(restTemplate);
return mockBuilder;
}
}
}
The test fails because it does not receive the response defined in TestConfig.restTemplateBuilder. I am providing both the REST requestor (testRest() method) and the REST responder (TestConfig.restTemplateBuilder). What am I doing wrong?
Here's the failure:
Status expected:<200> but was:<404>
Expected :200
Actual :404
<Click to see difference>
java.lang.AssertionError: Status expected:<200> but was:<404>
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:59)
at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:122)
at org.springframework.test.web.servlet.result.StatusResultMatchers.lambda$matcher$9(StatusResultMatchers.java:627)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:196)
at com.mycompany.RestTest.testRest(RestTest.java:54)
...
at java.base/java.lang.Thread.run(Thread.java:830)

Spring Controller gives me 404 status error

So I am attempting to write a basic Rest Controller in Spring Tool Suite with Spring annotations where I hit the endpoint "/health" and I receive the following message upon hitting the endpoint "Kafka Streaming App is healthy".
The only error I receive is the 404 status error when I check on the browser and I have already tried logging please help. I think the problem might be how I am calling the Controller in the Main Application class in Spring.
Main Application Class
package com.eds.kafka.streaming.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
//import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
//#EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
//#Configuration
//#EntityScan(basePackages = {"com.eds.kafka.streaming.model"})
//#ComponentScan(basePackages = { "com.eds.kafka.streaming.service", "com.eds.kafka.streaming.util", "com.eds.kafka.streaming.config", "com.eds.kafka.streaming.controller"}) //"com.tmobile.eds.infosec.volt.encr",
#ComponentScan(basePackages = {"com.eds.kafka.streaming"})
#SpringBootApplication
public class KafkaStreamingAppContainerApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(KafkaStreamingAppContainerApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(KafkaStreamingAppContainerApplication.class);
}
}
Controller Class
package com.eds.kafka.streaming.controller;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
#EnableAutoConfiguration
#PropertySource("classpath:application-${spring.profiles.active}.properties")
#RestController
public class MainController {
#RequestMapping(method = RequestMethod.GET, value = "/health", produces = "application/json")
#ResponseBody
public ResponseEntity home() {
System.out.println("Controller being configured!");
return new ResponseEntity("Kafka Streaming App is Healthy", HttpStatus.OK);
}
}
Please let me know if you have any advice and if needed I can provide a zipped version of the project if that is needed just message me.

SpringMVC & Spring in Action: can't redirect to home.jsp in chapter 5

I'm learning SpringMVC and maven these days with the book Spring in Action but i have a question now. The default request to "/" should be mapped to "home.jsp" but not. You can also see the same question described in the book forum.
https://forums.manning.com/posts/list/38046.page
Here are the codes:
package spittr.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{
#Override
protected String[] getServletMappings(){
return new String[]{ "/" };
}
#Override
protected Class<?>[] getRootConfigClasses(){
return new Class<?>[]{ RootConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses(){
return new Class<?>[]{ WebConfig.class };
}
}
package spittr.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#Configuration
#EnableWebMvc
#ComponentScan("spittr.web")
public class WebConfig extends WebMvcConfigurerAdapter{
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer){
configurer.enable();
}
}
package spittr.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
#Configuration
#ComponentScan(basePackages={"spitter"}, excludeFilters={
#Filter(type=FilterType.ANNOTATION, value=EnableWebMvc.class)
})
public class RootConfig {
}
package spittr.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
public class HomeController {
#RequestMapping(value="/", method=RequestMethod.GET)
public String home(){
return "home";
}
}
When i run this on tomcat 7.0, it should show home.jsp. However it still shows index.jsp.
-------------------- update -------------------------
The following test class indicates the controller class is right and this controller can response to the request "/" with home.jsp. So, where is wrong?
package spittr.web;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;
import org.junit.Test;
import org.springframework.test.web.servlet.MockMvc;
public class HomeControllerTest {
#Test
public void testHomePage() throws Exception{
HomeController controller = new HomeController();
MockMvc mockMvc = standaloneSetup(controller).build();
mockMvc.perform(get("/")).andExpect(view().name("home"));
}
}
update or add in your web.xml
<welcome-file-list>home.jsp</welcome-file-list>
If you do not have web.xml you can generate by
Dynamic Web Project –> RightClick –> Java EE Tools –> Generate
Deployment Descriptor Stub.
Also you can do JSP redirect using JSTL libraries in index.jsp to redirect to home.jsp
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:redirect url="/home.jsp"/>
seems to be a path problem.
First check your path mapping in web.xml file for exact url-pattern for which you are redirecting to dispatcher servlet.Assuming that you have home.jsp views created under
/WEB-INF/views/
folder.
I had the same issue while working on Eclipse, Tomcat 9.0 on my Mac. I have spend hours to see (this small code) that where I was wrong.
However, I was able to make it run on Windows machine with Eclipse and Tomcat 8.5 and 9.0 .
I have the code hosted on GitHub at https://github.com/shortduck/ManningChapter5_SpringMVC
This is a Maven project and not Gradle. Also see the HomeController has the value as value = "/home", this is working as well as '/' will work too. If you have having value as '/' make sure index.jsp or any other "home" page is not on the root.
My next target to find out why is this code not working on Mac.

Categories

Resources