Cannot load view in spring boot - java

I have been trying for hours now, can't seem to fix this. I have a simple Spring Boot Application.
These are the important files:
DemoApplication.java
package com.whatever.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import com.whatever.config.ConfigurationSettings;
#SpringBootApplication
#ComponentScan(basePackages = {"com.whatever.controllers", "com.whatever.config"})
public class DemoApplication{
public static void main(String[] args) {
Class[] sources = {DemoApplication.class, ConfigurationSettings.class};
SpringApplication.run(sources, args);
System.out.println("Hello WORLD!");
}
}
MainController.java
package com.whatever.controllers;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
#RestController
#RequestMapping("/")
public class MainController{
#RequestMapping("/welcome")
public ModelAndView welcome(){
System.out.println("WELCOME!");
ModelAndView mAndView = new ModelAndView();
mAndView.setViewName("welcome");
return mAndView;
}
}
ConfigurationSettings.java
package com.whatever.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#Configuration
public class ConfigurationSettings extends WebMvcConfigurationSupport{
#Bean
public InternalResourceViewResolver getResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/");
resolver.setSuffix(".jsp");
return resolver;
}
}
My project structure:
--src
--main
--com.whatever.config
--com.whatever.controllers
--com.whatever.demo
--webapp
--WEB-INF
welcome.jsp
However, it can't load the welcome.jsp page and I keep on getting the /error page.
I can't seem to understand the problem.
Any help is appreciated.
P.S: I get the "Hello world!" and "WELCOME!" messages on the console. So, I know the control reaches there.
The StackTrace says:
2018-07-17 16:40:19.869 DEBUG 11004 --- [-auto-13-exec-9] o.s.w.servlet.view.BeanNameViewResolver : No matching bean found for view name 'welcome'
2018-07-17 16:40:19.869 DEBUG 11004 --- [-auto-13-exec-9] o.s.b.f.s.DefaultListableBeanFactory : Invoking afterPropertiesSet() on bean with name 'welcome'
2018-07-17 16:40:19.869 DEBUG 11004 --- [-auto-13-exec-9] o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
2018-07-17 16:40:19.869 DEBUG 11004 --- [-auto-13-exec-9] o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
2018-07-17 16:40:19.870 DEBUG 11004 --- [-auto-13-exec-9] o.s.web.servlet.DispatcherServlet : Rendering view [org.springframework.web.servlet.view.JstlView: name 'welcome'; URL [/WEB-INF/welcome.jsp]] in DispatcherServlet with name 'dispatcherServlet'
2018-07-17 16:40:19.871 DEBUG 11004 --- [-auto-13-exec-9] o.s.web.servlet.view.JstlView : Forwarding to resource [/WEB-INF/welcome.jsp] in InternalResourceView 'welcome'
2018-07-17 16:40:19.872 DEBUG 11004 --- [-auto-13-exec-9] o.s.web.servlet.DispatcherServlet : Successfully completed request
2018-07-17 16:40:19.875 DEBUG 11004 --- [-auto-13-exec-9] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/error]
2018-07-17 16:40:19.875 DEBUG 11004 --- [-auto-13-exec-9] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Looking up handler method for path /error
2018-07-17 16:40:19.876 DEBUG 11004 --- [-auto-13-exec-9] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Did not find handler method for [/error]

You have add #RestController in your controller code,if you want to see the jsp page,you need to remove it and change to #Controller,since #RestController will add #ResponseBody to
you controller method automatically
package com.whatever.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import com.whatever.config.ConfigurationSettings;
#Controller("/")
public class MainController{
#RequestMapping("/welcome")
public ModelAndView welcome(){
System.out.println("WELCOME!");
ModelAndView mAndView = new ModelAndView();
mAndView.setViewName("welcome");
return mAndView;
}
}

You have used #RestController , rather use #Controller , It will solve your problem
Please try as below ,
package com.whatever.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import com.whatever.config.ConfigurationSettings;
#Controller
public class MainController{
#RequestMapping("/welcome")
public String welcome(){
System.out.println("WELCOME!");
return "welcome";
}
}

Related

Getting exception that says no mapping, when I have the mapping

My application is running with an exception. When I try to post to localhost:8080/addUser I get the error that there is no mapping. However I have it in my UserController.java:
2021-10-03 20:28:04.852 INFO 9896 --- [ngodb.net:27017] org.mongodb.driver.cluster : Exception in monitor thread while connecting to server edumeet-shard-00-01.egesp.mongodb.net:27017
com.mongodb.MongoSocketReadException: Prematurely reached end of stream
at com.mongodb.internal.connection.SocketStream.read(SocketStream.java:112) ~[mongodb-driver-core-4.2.3.jar:na]
at com.mongodb.internal.connection.SocketStream.read(SocketStream.java:131) ~[mongodb-driver-core-4.2.3.jar:na]
at com.mongodb.internal.connection.InternalStreamConnection.receiveResponseBuffers(InternalStreamConnection.java:647) ~[mongodb-driver-core-4.2.3.jar:na]
at com.mongodb.internal.connection.InternalStreamConnection.receiveMessageWithAdditionalTimeout(InternalStreamConnection.java:512) ~[mongodb-driver-core-4.2.3.jar:na]
at com.mongodb.internal.connection.InternalStreamConnection.receiveCommandMessageResponse(InternalStreamConnection.java:355) ~[mongodb-driver-core-4.2.3.jar:na]
at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceive(InternalStreamConnection.java:279) ~[mongodb-driver-core-4.2.3.jar:na]
at com.mongodb.internal.connection.CommandHelper.sendAndReceive(CommandHelper.java:83) ~[mongodb-driver-core-4.2.3.jar:na]
at com.mongodb.internal.connection.CommandHelper.executeCommand(CommandHelper.java:33) ~[mongodb-driver-core-4.2.3.jar:na]
at com.mongodb.internal.connection.InternalStreamConnectionInitializer.initializeConnectionDescription(InternalStreamConnectionInitializer.java:107) ~[mongodb-driver-core-4.2.3.jar:na]
at com.mongodb.internal.connection.InternalStreamConnectionInitializer.initialize(InternalStreamConnectionInitializer.java:62) ~[mongodb-driver-core-4.2.3.jar:na]
at com.mongodb.internal.connection.InternalStreamConnection.open(InternalStreamConnection.java:144) ~[mongodb-driver-core-4.2.3.jar:na]
at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.lookupServerDescription(DefaultServerMonitor.java:188) ~[mongodb-driver-core-4.2.3.jar:na]
at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:144) ~[mongodb-driver-core-4.2.3.jar:na]
at java.base/java.lang.Thread.run(Thread.java:835) ~[na:na]
2021-10-03 20:28:05.681 INFO 9896 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2021-10-03 20:28:05.692 INFO 9896 --- [ restartedMain] com.example.login.LoginApplication : Started LoginApplication in 3.95 seconds (JVM running for 4.612)
2021-10-03 20:28:17.960 INFO 9896 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-10-03 20:28:17.960 INFO 9896 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2021-10-03 20:28:17.996 INFO 9896 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Completed initialization in 36 ms
2021-10-03 20:28:18.025 WARN 9896 --- [nio-8080-exec-2] o.s.web.servlet.PageNotFound : No mapping for POST /addUser
2021-10-03 20:28:18.032 WARN 9896 --- [nio-8080-exec-2] o.s.web.servlet.PageNotFound : No mapping for POST /error
UserController.java
package com.example.login.User;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#Controller
#RestController
public class UserController {
private final UserRepository userRepository;
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}
#RequestMapping(path = "/addUser", method = RequestMethod.POST)
public String addUser(#RequestBody User user) {
userRepository.save(user);
return "added user with id: " + user.getId();
}
#RequestMapping(path = "/getAllUsers", method = RequestMethod.GET)
public List<User> getAllUsers() {
return userRepository.findAll();
}
#RequestMapping(path = "/getAllUsers/{id}", method = RequestMethod.GET)
public Optional<User> getUser(#PathVariable String id) {
return userRepository.findById(id);
}
#RequestMapping(path = "/removeUser", method = RequestMethod.DELETE)
public String deleteUser(#PathVariable String id) {
userRepository.deleteById(id);
return "removed user with id" + id;
}
}
LoginApplication.java
package com.example.login;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
#SpringBootApplication
#EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class,WebMvcAutoConfiguration.class})
public class LoginApplication {
public static void main(String[] args) {
SpringApplication.run(LoginApplication.class, args);
}
}
you should change path to value as shown below:
#RequestMapping(path = "/addUser", method = RequestMethod.POST)
public String addUser(#RequestBody User user) {
userRepository.save(user);
return "added user with id: " + user.getId();
}
change to
#RequestMapping(value = "/addUser", method = RequestMethod.POST)
public String addUser(#RequestBody User user) {
userRepository.save(user);
return "added user with id: " + user.getId();
}

Stack overflow calling Spring authenticationManager.authenticate

I started with a spring boot starter project version 2.3.5, but when I call authenticationManager.authenticate I get a stack overflow error.
java.lang.StackOverflowError: null
at ch.qos.logback.classic.Logger.callTurboFilters(Logger.java:751) ~[logback-classic-1.2.3.jar:na]
at ch.qos.logback.classic.Logger.isDebugEnabled(Logger.java:469) ~[logback-classic-1.2.3.jar:na]
at ch.qos.logback.classic.Logger.isDebugEnabled(Logger.java:465) ~[logback-classic-1.2.3.jar:na]
at org.apache.commons.logging.LogAdapter$Slf4jLog.isDebugEnabled(LogAdapter.java:310) ~[spring-jcl-5.2.10.RELEASE.jar:5.2.10.RELEASE]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:186) ~[spring-security-core-5.3.5.RELEASE.jar:5.3.5.RELEASE]
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:524) ~[spring-security-config-5.3.5.RELEASE.jar:5.3.5.RELEASE]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:219) ~[spring-security-core-5.3.5.RELEASE.jar:5.3.5.RELEASE]
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:524) ~[spring-security-config-5.3.5.RELEASE.jar:5.3.5.RELEASE]
Initially I did not use the user variable and instead created created the new UsernamePasswordAuthenticationToken inside the authenticationManager.authenticate either way I get the stack overflow error. I also have tried #PostMapping instead of #RequestMapping and Method. All of these cause the same failure.
I get the printline that says I am "in /Authenticate" with the following.
2020-11-09 16:20:32.141 DEBUG 10456 --- [nio-8080-exec-2] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to io.javabrains.springsecurityjwt.HelloResource#createAuthenticationToken(AuthenticationRequest)
2020-11-09 16:20:32.188 DEBUG 10456 --- [nio-8080-exec-2] m.m.a.RequestResponseBodyMethodProcessor : Read "application/json;charset=UTF-8" to [io.javabrains.springsecurityjwt.models.AuthenticationRequest#758a32c5]
in /Authenticate
2020-11-09 16:20:32.197 DEBUG 10456 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Failed to complete request: org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.StackOverflowError
2020-11-09 16:20:32.201 ERROR 10456 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.StackOverflowError] with root cause
Here is the full code of the Class
Thank you for any info or things I should try!
package io.javabrains.springsecurityjwt;
import io.javabrains.springsecurityjwt.models.AuthenticationRequest;
import io.javabrains.springsecurityjwt.models.AuthenticationResponse;
import io.javabrains.springsecurityjwt.services.MyUserDetailsService;
import io.javabrains.springsecurityjwt.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
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;
#RestController
public class HelloResource {
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private MyUserDetailsService userDetailsService;
#Autowired
private JwtUtil jwtTokenUtil;
#RequestMapping( "/hello")
public String hello() {
return "Hello World";
}
#RequestMapping(value = "/authenticate", method = RequestMethod.POST)
public ResponseEntity<?> createAuthenticationToken(#RequestBody AuthenticationRequest authenticationRequest) throws Exception {
UsernamePasswordAuthenticationToken user = new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword());
System.out.println("in /Authenticate");
try {
authenticationManager.authenticate(
user
// new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword())
);
System.out.println("in Try in /Authenticate");
} catch (BadCredentialsException e) {
throw new Exception("Incorrect Username or Password", e);
}
System.out.println("outside the try catch");
final UserDetails userDetails = userDetailsService
.loadUserByUsername(authenticationRequest.getUsername());
final String jwt = jwtTokenUtil.generateToken(userDetails);
return ResponseEntity.ok(new AuthenticationResponse(jwt));
}
}

After adding elasticsearch support, Spring Boot complain BeanCreationException with nested IllegalStateException No association found

I have run into a strange problem. I created a project with Spring Boot 2.0.1 with redis, mongodb and elasticsearch . Before adding elasticsearch, everything runs smoothly, but after I add elasticsearch, Spring Boot starts complaining,but the error looks like not related to elasticsearch, it complains that it could not create userRepo 。 Please get noticed I used lombok's #RequiredArgsConstructor to generate constructor to make injection work, so it should not be #autowired issue, Anyone can help me out? thank in adavance
2018-05-02 16:12:58.687 INFO 74244 --- [ restartedMain] o.s.b.w.servlet.ServletRegistrationBean : Servlet dispatcherServlet mapped to [/]
2018-05-02 16:12:59.037 WARN 74244 --- [ restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityConfig' defined in file [/Users/wangpeng/workspace/books/gtm/backend/api/out/production/classes/dev/local/gtm/api/config/SecurityConfig.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userDetailsServiceImpl' defined in file [/Users/wangpeng/workspace/books/gtm/backend/api/out/production/classes/dev/local/gtm/api/security/UserDetailsServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepo': Invocation of init method failed; nested exception is java.lang.IllegalStateException: No association found!
2018-05-02 16:12:59.037 DEBUG 74244 --- [ restartedMain] h.i.c.PoolingHttpClientConnectionManager : Connection manager is shutting down
2018-05-02 16:12:59.037 DEBUG 74244 --- [ restartedMain] h.i.c.PoolingHttpClientConnectionManager : Connection manager shut down
Process finished with exit code 1
my subproject's build.gradle is as follows:
apply plugin: 'org.springframework.boot'
configurations {
compile.exclude module: 'spring-boot-starter-tomcat'
}
bootRun {
systemProperties = System.properties as Map<String, ?>
}
test {
systemProperties['spring.profiles.active'] = 'test'
}
dependencies {
implementation("io.springfox:springfox-swagger2:${springFoxVersion}")
implementation("io.springfox:springfox-bean-validators:${springFoxVersion}")
implementation("io.springfox:springfox-swagger-ui:${springFoxVersion}")
implementation("org.springframework.boot:spring-boot-starter-undertow")
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("io.jsonwebtoken:jjwt:0.9.0")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.boot:spring-boot-starter-aop")
implementation("org.zalando:problem-spring-web:0.20.1")
implementation("org.redisson:redisson:${redissonVersion}")
implementation("com.fasterxml.jackson.module:jackson-module-afterburner")
implementation("org.springframework.boot:spring-boot-starter-data-mongodb")
implementation("org.springframework.boot:spring-boot-starter-data-redis")
implementation("com.github.vanroy:spring-boot-starter-data-jest:3.1.2.RELEASE")
testImplementation("org.springframework.security:spring-security-test")
}
The UserRepo is as follows
package dev.local.gtm.api.repository;
import dev.local.gtm.api.domain.User;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.time.Instant;
import java.util.List;
import java.util.Optional;
#Repository
public interface UserRepo extends MongoRepository<User, String> {
String USERS_BY_LOGIN_CACHE = "usersByLogin";
String USERS_BY_MOBILE_CACHE = "usersByMobile";
String USERS_BY_EMAIL_CACHE = "usersByEmail";
#Cacheable(cacheNames = USERS_BY_MOBILE_CACHE)
Optional<User> findOneByMobile(#Param("mobile") String mobile);
#Cacheable(cacheNames = USERS_BY_EMAIL_CACHE)
Optional<User> findOneByEmailIgnoreCase(#Param("email") String email);
#Cacheable(cacheNames = USERS_BY_LOGIN_CACHE)
Optional<User> findOneByLogin(#Param("login") String login);
Page<User> findAllByLoginNot(Pageable pageable, #Param("login") String login);
List<User> findAllByActivatedIsFalseAndCreatedDateBefore(Instant dateTime);
}
The Spring Security Configuration is as follows:
package dev.local.gtm.api.config;
import dev.local.gtm.api.security.AuthoritiesConstants;
import dev.local.gtm.api.security.jwt.JWTConfigurer;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
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.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
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 org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.filter.CorsFilter;
import org.zalando.problem.spring.web.advice.security.SecurityProblemSupport;
import javax.annotation.PostConstruct;
#RequiredArgsConstructor
#Configuration
#ComponentScan(basePackages = "dev.local.gtm.api")
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
#Import(SecurityProblemSupport.class)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final AuthenticationManagerBuilder authenticationManagerBuilder;
private final UserDetailsService userDetailsService;
private final CorsFilter corsFilter;
private final SecurityProblemSupport problemSupport;
private final JWTConfigurer jwtConfigurer;
#PostConstruct
public void init() {
try {
authenticationManagerBuilder
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
} catch (Exception e) {
throw new BeanInitializationException("安全配置失败", e);
}
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
public void configure(WebSecurity web) {
web.ignoring()
.antMatchers(HttpMethod.OPTIONS, "/**")
.antMatchers("/app/**/*.{js,html}")
.antMatchers("/i18n/**")
.antMatchers("/content/**")
.antMatchers("/swagger-ui/index.html")
.antMatchers("/test/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
.exceptionHandling()
.authenticationEntryPoint(problemSupport)
.accessDeniedHandler(problemSupport)
.and()
.csrf()
.disable()
.headers()
.frameOptions()
.disable()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/**").authenticated()
.antMatchers("/websocket/tracker").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/websocket/**").permitAll()
.antMatchers("/management/health").permitAll()
.antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/v2/api-docs/**").permitAll()
.antMatchers("/swagger-resources/configuration/ui").permitAll()
.antMatchers("/swagger-ui/index.html").permitAll()
.and()
.apply(jwtConfigurer);
}
}
The UserDetailServiceImpl is as follows:
package dev.local.gtm.api.security;
import dev.local.gtm.api.config.Constants;
import dev.local.gtm.api.domain.User;
import dev.local.gtm.api.repository.UserRepo;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import lombok.val;
import org.hibernate.validator.internal.constraintvalidators.hv.EmailValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import java.util.Locale;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
#Log4j2
#RequiredArgsConstructor
#Component("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
private final UserRepo userRepo;
#Override
public UserDetails loadUserByUsername(final String login) {
log.debug("正在对用户名为 {} 的用户进行鉴权", login);
if (new EmailValidator().isValid(login, null)) {
val userByEmailFromDatabase = userRepo.findOneByEmailIgnoreCase(login);
return userByEmailFromDatabase.map(user -> createSpringSecurityUser(login, user))
.orElseThrow(() -> new UsernameNotFoundException("系统中不存在 email 为 " + login + " 的用户"));
}
if (Pattern.matches(Constants.MOBILE_REGEX, login)) {
val userByMobileFromDatabase = userRepo.findOneByMobile(login);
return userByMobileFromDatabase.map(user -> createSpringSecurityUser(login, user))
.orElseThrow(() -> new UsernameNotFoundException("系统中不存在手机号为 " + login + " 的用户"));
}
String lowercaseLogin = login.toLowerCase(Locale.ENGLISH);
val userByLoginFromDatabase = userRepo.findOneByLogin(lowercaseLogin);
return userByLoginFromDatabase.map(user -> createSpringSecurityUser(lowercaseLogin, user))
.orElseThrow(() -> new UsernameNotFoundException("User " + lowercaseLogin + " was not found in the database"));
}
private org.springframework.security.core.userdetails.User createSpringSecurityUser(String lowercaseLogin, User user) {
if (!user.isActivated()) {
throw new UserNotActivatedException("用户 " + lowercaseLogin + " 没有激活");
}
val grantedAuthorities = user.getAuthorities().stream()
.map(authority -> new SimpleGrantedAuthority(authority.getName()))
.collect(Collectors.toList());
return new org.springframework.security.core.userdetails.User(user.getLogin(),
user.getPassword(),
grantedAuthorities);
}
}
[update] After I change spring-boot-jest to spring-boot-elasticsearch the error is more specific. it now says the elasticsearchTemplate bean is not defined, but in fact it is.
2018-05-02 17:04:59.776 WARN 76262 --- [ restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityConfig' defined in file [/Users/wangpeng/workspace/books/gtm/backend/api/out/production/classes/dev/local/gtm/api/config/SecurityConfig.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userDetailsService' defined in file [/Users/wangpeng/workspace/books/gtm/backend/api/out/production/classes/dev/local/gtm/api/security/UserDetailsServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepo': Cannot resolve reference to bean 'elasticsearchTemplate' while setting bean property 'elasticsearchOperations'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'elasticsearchTemplate' available
2018-05-02 17:04:59.805 INFO 76262 --- [ restartedMain] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2018-05-02 17:04:59.822 INFO 76262 --- [ restartedMain] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2018-05-02 17:04:59.925 ERROR 76262 --- [ restartedMain] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in dev.local.gtm.api.security.UserDetailsServiceImpl required a bean named 'elasticsearchTemplate' that could not be found.
Action:
Consider defining a bean named 'elasticsearchTemplate' in your configuration.
Process finished with exit code 1
The bean is defined in ElasticConfig as follows
package dev.local.gtm.api.config;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.elasticsearch.client.Client;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.EntityMapper;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import java.io.IOException;
#Configuration
#EnableConfigurationProperties(ElasticsearchProperties.class)
#ConditionalOnProperty("spring.data.elasticsearch.cluster-nodes")
public class ElasticConfig {
#Bean
public ElasticsearchTemplate elasticsearchTemplate(Client client, Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder) {
return new ElasticsearchTemplate(client, new CustomEntityMapper(jackson2ObjectMapperBuilder.createXmlMapper(false).build()));
}
public class CustomEntityMapper implements EntityMapper {
private ObjectMapper objectMapper;
public CustomEntityMapper(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
}
#Override
public String mapToString(Object object) throws IOException {
return objectMapper.writeValueAsString(object);
}
#Override
public <T> T mapToObject(String source, Class<T> clazz) throws IOException {
return objectMapper.readValue(source, clazz);
}
}
}
It turns out I reuse same entities for both Elasticsearch and MongoDB, which raise the exception. So I managed to get it resolved by separating the entities

Spring - beans getting initialize twice

I am aware about the tale of two context in spring. I understand that there are two context - one for ContextLoaderListener and another for DispatcherServlet.
I am trying to use all java config for the project and remove the web.xml file completely. So I have use AbstractAnnotationConfigDispatcherServletInitializer class. But I am facing the problem in that. When I start the server, I can see the beans are created twice. Can you help me understand, what am I doing wrong.
As you can see I tried different annotation for RootConfig file so that it ignores the Config referenced in EnableWebMvc class and few other combinations but it always scans those classes and initiates the bean. (see the log line viewResolver called and datasource bean creation are printed twice)
Here are project details:
logs:
Jan 11, 2018 12:20:57 AM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 5220 ms
INFO : org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization started
INFO : org.springframework.web.context.support.AnnotationConfigWebApplicationContext - Refreshing Root WebApplicationContext: startup date [Thu Jan 11 00:21:37 IST 2018]; root of context hierarchy
INFO : org.springframework.web.context.support.AnnotationConfigWebApplicationContext - Registering annotated classes: [class com.nikdroid.poc.config.RootConfig]
INFO : org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
datasource bean creation
WARN : org.hibernate.engine.jdbc.internal.JdbcServicesImpl - HHH000342: Could not obtain connection to query metadata : Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/],methods=[GET]}" onto public org.springframework.web.servlet.ModelAndView com.nikdroid.poc.controller.HomeController.home()
INFO : org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler]
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter - Looking for #ControllerAdvice: Root WebApplicationContext: startup date [Thu Jan 11 00:21:37 IST 2018]; root of context hierarchy
viewResolver called
INFO : org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 12563 ms
INFO : org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'dispatcher': initialization started
INFO : org.springframework.web.context.support.AnnotationConfigWebApplicationContext - Refreshing WebApplicationContext for namespace 'dispatcher-servlet': startup date [Thu Jan 11 00:21:49 IST 2018]; parent: Root WebApplicationContext
INFO : org.springframework.web.context.support.AnnotationConfigWebApplicationContext - Registering annotated classes: [class com.nikdroid.poc.config.WebConfig]
INFO : org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
datasource bean creation
WARN : org.hibernate.engine.jdbc.internal.JdbcServicesImpl - HHH000342: Could not obtain connection to query metadata : Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/],methods=[GET]}" onto public org.springframework.web.servlet.ModelAndView com.nikdroid.poc.controller.HomeController.home()
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter - Looking for #ControllerAdvice: WebApplicationContext for namespace 'dispatcher-servlet': startup date [Thu Jan 11 00:21:49 IST 2018]; parent: Root WebApplicationContext
INFO : org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler]
viewResolver called
INFO : org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'dispatcher': initialization completed in 2643 ms
Jan 11, 2018 12:22:08 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 71461 ms
And
AbstractAnnotationConfigDispatcherServletInitializer
package com.nikdroid.poc.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] {RootConfig.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] {WebConfig.class};
}
#Override
protected String[] getServletMappings() {
return new String[] {"/"};
}
}
WebConfig
package com.nikdroid.poc.config;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
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.context.support.ResourceBundleMessageSource;
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("com.nikdroid.poc")*/
/*#ComponentScan(basePackageClasses={ControllerMarker.class, ServiceMarker.class, DaoMarker.class})*/
#ComponentScan(basePackages = "com.nikdroid.poc",
excludeFilters = {
#Filter(type = FilterType.ASSIGNABLE_TYPE,
value = {
WebConfig.class
})
})
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public ViewResolver viewResolver() {
System.out.println("viewResolver called");
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();
}
#Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}
}
RootConfig
package com.nikdroid.poc.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={"com.nikdroid"},
excludeFilters={
#Filter(type=FilterType.ANNOTATION, value=EnableWebMvc.class)
})
/*#ComponentScan(basePackageClasses={ControllerMarker.class, ServiceMarker.class, DaoMarker.class},
excludeFilters={
#Filter(type=FilterType.ANNOTATION, value=EnableWebMvc.class)
})*/
/*#ComponentScan(basePackages = "com.nikdroid.poc",
excludeFilters = {
#Filter(type = FilterType.ASSIGNABLE_TYPE,
value = {
com.nikdroid.poc.config.WebConfig.class
})
})*/
/*#ComponentScan(basePackages = "com.nikdroid.poc",
excludeFilters = #Filter(type=FilterType.REGEX,pattern="com\\.nikdroid\\.poc\\.config\\..*")) */
/*#ComponentScan("com.nikdroid.poc")*/
public class RootConfig {
}
JPAConfig
package com.nikdroid.poc.config;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.SessionFactory;
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.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#Configuration
#ComponentScan({ "com.nikdroid.poc" })
#EnableTransactionManagement
#PropertySource(value = { "classpath:application.properties" })
public class JPAConfig {
#Autowired
private Environment environment;
#Bean
public DataSource dataSource() {
System.out.println("datasource bean creation");
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
ds.setUrl(environment.getRequiredProperty("jdbc.url"));
ds.setUsername(environment.getRequiredProperty("jdbc.username"));
ds.setPassword(environment.getRequiredProperty("jdbc.password"));
return ds;
}
#Autowired
#Bean
public LocalSessionFactoryBean sessionFactory(DataSource dataSource) {
LocalSessionFactoryBean sfb = new LocalSessionFactoryBean();
sfb.setDataSource(dataSource);
sfb.setPackagesToScan(new String[] { "com.nikdroid.poc" });//TODO find alternate
sfb.setHibernateProperties(hibernateProperties());
return sfb;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
return properties;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}

spring web-mvc 4 java config doesn't work

I'm trying to run elementary spring-4 web-mvc application without xml configuration at all. I've looked spring documentation and examples, but it didn't work for me.
My controller:
package com.nikolay.exam.controller;
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;
#Controller
public class HomeController {
#RequestMapping(value = "/home", method = RequestMethod.GET)
#ResponseBody
public String home() {
return "Hello world!";
}
}
AppConfig:
package com.nikolay.exam.config;
import org.springframework.context.annotation.Configuration;
#Configuration
public class AppConfig {
}
WebConfig:
package com.nikolay.exam.config;
import com.nikolay.exam.controller.HomeController;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public HomeController homeController() {
return new HomeController();
}
}
And WebInitializer:
package com.nikolay.exam.config;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
public class WebInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
root.setConfigLocation("com.nikolay.exam.config");
servletContext.addListener(new ContextLoaderListener(root));
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(root));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/*");
}
}
But when I run my application on tomcat I receive an error:
14-Feb-2015 11:35:29.825 WARNING [http-nio-8080-exec-1] org.springframework.web.servlet.PageNotFound.noHandlerFound No mapping found for HTTP request with URI [/home/] in DispatcherServlet with name 'dispatcher'
14-Feb-2015 11:35:32.766 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory /home/nikolay/apache-tomcat-8.0.9/webapps/manager
14-Feb-2015 11:35:32.904 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /home/nikolay/apache-tomcat-8.0.9/webapps/manager has finished in 136 ms
14-Feb-2015 11:35:34.888 WARNING [http-nio-8080-exec-3] org.springframework.web.servlet.PageNotFound.noHandlerFound No mapping found for HTTP request with URI [/home/] in DispatcherServlet with name 'dispatcher'
I think it's the way you register your config class that is not correct.
Try using the AnnotationConfigWebApplicationContext#register instead.
AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
appContext.register(WebConfig.class);
Probably you need to change
dispatcher.addMapping("/*");
to
dispatcher.addMapping("/");

Categories