I've been trying to configure Spring without Spring Boot.
I added a Tomcat, created the MainController class, and configured the Dispatcher Servlet
but in an endpoint 'http://localhost:8080/main/hello I receive 404.
I think it is problem in the ServletDispatcherConfig.
This is my ServletDispatcherConfig class
#Component
public class ServletDispatcherConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] {SpringConfig.class};
}
#Override
protected String[] getServletMappings() {
return new String[] {"/"};
}
}
and this is my SpringConfig class
#Configuration
#ComponentScan("example.test")
#EnableWebMvc
public class SpringConfig {
private final ApplicationContext applicationContext;
#Autowired
public SpringConfig(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
#Bean
public SpringResourceTemplateResolver templateResolver() {
var resolver = new SpringResourceTemplateResolver();
resolver.setCacheable(true);
resolver.setPrefix("/WEB-INF/templates/");
resolver.setSuffix(".html");
resolver.setApplicationContext(applicationContext);
resolver.setTemplateMode(TemplateMode.HTML);
return resolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
var engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver());
engine.setEnableSpringELCompiler(true); // delete if any bugs will be
return engine;
}
#Bean
public ThymeleafViewResolver viewResolver() {
var templateResolver = new ThymeleafViewResolver();
templateResolver.setTemplateEngine(templateEngine());
return templateResolver;
}
}
my MainController class
#Controller
#RequestMapping("/main")
public class MainController {
#GetMapping("/first")
public String main() {
return "/main";
}
#GetMapping("/hello")
public String hello() {
return "/main";
}
}
Related
I have a project based on SpringMVC 5 and an error happened when I tried to run it on JBoss EAP 7.3.
14:33:14,134 DEBUG
[org.springframework.beans.factory.support.DefaultListableBeanFactory]
(ServerService Thread Pool -- 99) Creating shared instance of
singleton bean 'userDetailsService'
14:33:14,140 ERROR [org.springframework.web.context.ContextLoader]
(ServerService Thread Pool -- 99) Context initialization failed:
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'springSecurityFilterChain' defined in
org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration:
Bean instantiation via factory method failed;......nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type 'com.aaa.bbb.security.service.UserService'
available: expected at least 1 bean which qualifies as autowire
candidate. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
Here's the code of class "UserDetailsServiceImpl":
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
private UserService userService;
#Autowired
private SessionUtils sessionUtils;
#Override
public UserDetails loadUserByUsername(String userID) throws UsernameNotFoundException {
User user = userService.get(userID);
if (user == null) throw new UsernameNotFoundException("Could not find user");
sessionUtils.expireUserSessions(user.getUser_name()); // Force expire other session
return new UserDetailsInfo(user);
}
}
And here's the code of class "UserService":
#Service
public class UserService {
#Autowired
private UserRepository userRepository;
public User get(String id) {
return userRepository.findById(id).get();
}
public User getuUserByUsername(String user_name) {
return userRepository.getuUserByUsername(user_name);
}
public int incLoginErrorCount(String id) {
return userRepository.incLoginErrorCount(id);
}
public int resetLoginErrorCount(String id) {
return userRepository.resetLoginErrorCount(id);
}
public int lockCount(String id) {
return userRepository.lockCount(id);
}
public int changeUPassword(String id, String password) {
return userRepository.changeUPassword(id, password);
}
}
And I'm using "WebAppInitializer":
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
private String TMP_FOLDER = "/tmp";
private int MAX_UPLOAD_SIZE = 5 * 1024 * 1024;
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { WebSecurityConfig.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebMvcConfig.class};
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
protected Filter[] getServletFilters() {
return new Filter[] { new HiddenHttpMethodFilter(), new MultipartFilter(),
new OpenEntityManagerInViewFilter() };
}
#Override
protected void registerDispatcherServlet(ServletContext servletContext) {
super.registerDispatcherServlet(servletContext);
servletContext.addListener(new HttpSessionEventPublisher());
}
#Override
protected void customizeRegistration(ServletRegistration.Dynamic registration) {
MultipartConfigElement multipartConfigElement = new MultipartConfigElement(TMP_FOLDER, MAX_UPLOAD_SIZE,
MAX_UPLOAD_SIZE * 2, MAX_UPLOAD_SIZE / 2);
registration.setMultipartConfig(multipartConfigElement);
}
}
To call "WebMvcConfig":
#ComponentScan(basePackages = {"com.aaa.bbb"})
public class WebMvcConfig implements WebMvcConfigurer {
#Bean(name = "viewResolver")
public InternalResourceViewResolver getViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(100000);
return multipartResolver;
}
#Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**", "/resources/**", "/resources/**", "/webjars/**", "/log/**")
.addResourceLocations("classpath:/css/", "classpath:/js/", "classpath:/json/", "/webjars/", "/META-INF/");
}
#Bean
public MessageSource messageSource() {
ResourceBundleMessageSource source = new ResourceBundleMessageSource();
source.setBasenames("message/messages");
source.setUseCodeAsDefaultMessage(true);
source.setDefaultEncoding("UTF-8");
return source;
}
}
If #ComponentScan worked, this error should not happen.
Thank you!
I think you should use #Service annotation on the UserDetailsServiceImpl class too. Since it is not annotated, componentScan doesn't know that it should autowire the services inside it. So UserDetailsServiceImpl class should look like this.
#Service
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
private UserService userService;
#Autowired
private SessionUtils sessionUtils;
#Override
public UserDetails loadUserByUsername(String userID) throws UsernameNotFoundException {
User user = userService.get(userID);
if (user == null) throw new UsernameNotFoundException("Could not find user");
sessionUtils.expireUserSessions(user.getUser_name()); // Force expire other session
return new UserDetailsInfo(user);
}
}
What is wrong in below Java code and what does it mean? Can anyone please help me to solve this:
java.lang.IllegalArgumentException: Failed to register servlet with name 'dispatcher'.Check if there is another servlet registered under the same name.
AppConfig.java
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.kk.kk.config")
public class AppConfig {
//Define a bean for ViewResolver
#Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/view/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
DispatcherServletInitializer.java
public class DispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
//TODO Auto-generated method stub
return null;
}
#Override
protected Class<?>[] getServletConfigClasses(){
return new Class[] {AppConfig.class};
}
#Override
protected String[] getServletMappings(){
return new String[] {"/"};
}
}
AppController.java
#Controller
public class AppController {
#GetMapping("/")
public String showHome(){
return "home";
}
}
You can implement WebMvcConfigurer :
Try this:
#Configuration
#EnableWebMvc
public class AppConfig implements WebMvcConfigurer{
}
#TransactionConfiguration
#Transactional
#ContextConfiguration(classes=AnnotationConfigContextLoaderUtils.class)
#WebAppConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
public class AnyTest extends TestMachine {
#Inject
private AccountDao accDao; //ALLWAYS NULL
I run the test with:
TestNG testNG = new TestNG();
AppConfig.java
#Bean
public SessionScope sessionScope(){
return new SessionScope();
}
#Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
#Bean
public JdbcTemplate jdbcTemplate() throws ConfigurationException {
return new JdbcTemplate(dataSource());
}
#Bean
public DataSource dataSource() throws ConfigurationException {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
//DB INITIALIZE
}
#Bean(name = "sessionFactory")
public LocalSessionFactoryBean sessionFactory() throws ConfigurationException {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource());
sessionFactoryBean.setPackagesToScan("package.model");
sessionFactoryBean.setHibernateProperties(hibProperties());
return sessionFactoryBean;
}
#Bean
public HibernateTransactionManager transactionManager() throws ConfigurationException {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
private Properties hibProperties() {
Properties properties = new Properties();
properties.put("hibernate.hbm2ddl.auto", hibernateAuto);
properties.put("hibernate.dialect", hibernateDialect);
properties.put("hibernate.show_sql", showSQL);
return properties;
}
SpringMVCInitializer.java
public class SpringMVCInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] {AppConfig.class, SpringMVCConfiguration.class, SimpleCORSFilter.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
Maven dependency versions:
<spring-version>4.0.3.RELEASE</spring-version>
<spring-test>4.0.3.RELEASE</spring-test>
<testNG-Version>6.9.4</testNG-Version>
<hibernate.version>4.1.5.Final</hibernate.version>
<hibernate-validator>4.2.0.Final</hibernate-validator>
<mysql.connector.version>5.1.32</mysql.connector.version>
<dbcp.version>1.4</dbcp.version>
Why I can't inject any bean to a test?
Note: I used #Autowired and it did not work too.
One sugestion is inject the session in the main method I used to run the test.
Is any way to make this?
I resolved this problem creating a Static Class and injecting the dependencies into this class in a controller.
Controller:
#Controller
public class InitController {
#Inject
public InitController(TestDao testDao, InsynctivePropertyDao propertyDao, ServletContext servletContext, AccountDao accDao, CrossBrowserAccountDao crossDao, CreatePersonFormDao createPersonFormDao, TestSuiteDao testSuiteDao) {
HibernateUtil.init(testDao, propertyDao, servletContext, accDao, crossDao, createPersonFormDao, testSuiteDao);
}
}
HibernateUtil.java
public class HibernateUtil {
public static CrossBrowserAccountDao crossDao;
public static TestDao testDao;
public static synchronized void init(TestDao testDao, InsynctivePropertyDao propertyDao, ServletContext servletContext, AccountDao accDao, CrossBrowserAccountDao crossDao, CreatePersonFormDao createPersonFormDao, TestSuiteDao testSuiteDao){
HibernateUtil.crossDao = crossDao;
HibernateUtil.testDao = testDao;
}
}
I have spring mvc project and i don't use #Autowired because my object always is null. How me load JavaConfig for using #Autowired, i do not use any *.xml file.
This is my controller with #Autowired field for service.
#Controller
public class WebController {
#Autowired
private ServiceWeb serviceWeb;
public void setServiceWeb(ServiceWeb serviceWeb) {
this.serviceWeb = serviceWeb;
}
...
}
This is my AbstractAnnotationConfigDispatcherServletInitializer
public class ServletInit extends
AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { SpringRootConfig.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { SpringWebConfig.class};
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
SpringRootConfig & SpringWebConfig
#Configuration
#ComponentScan({"web.controller"})
public class SpringRootConfig {
}
#EnableWebMvc
#Configuration
#ComponentScan({ "web.controller"})
#Import({SecurityConfig.class})
public class SpringWebConfig extends WebMvcConfigurerAdapter{
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver
= new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
Class for #Autowiring
#Configuration
public class ConfigurationBean {
#Bean
public ServiceWeb serviceWeb(){
return new ServiceWebImpl();
}
}
Register context for spring, but where need write Init.class for loading this config ?
public class Init implements WebApplicationInitializer {
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(ConfigurationBean.class);
servletContext.addListener(new ContextLoaderListener(ctx));
ctx.setServletContext(servletContext);
}
}
Pls try this...
#Service
public class ServiceWebImpl implements ServiceWeb {
}
ServiceWeb bean is created inside ConfigurationBean class and its not visible at spring context level for autowiring.
Maven Dependencies
<!-- SPRING MVC -->
<spring-version>4.0.3.RELEASE</spring-version>
<spring-test-version>4.2.1.RELEASE</spring-test-version>
<!-- TESTS -->
<junit-Version>4.11</junit-Version>
<!-- DATA BASE -->
<hibernate.version>4.1.5.Final</hibernate.version>
<hibernate-validator>4.2.0.Final</hibernate-validator>
<mysql.connector.version>5.1.32</mysql.connector.version>
AccountDao.java
#Repository
#Transactional
public class AccountDao {
private final SessionFactory sessionFactory;
#Inject
public AccountDao(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
[...]
}
Test
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {SpringMVCInitializer.class}, loader=AnnotationConfigContextLoader.class)
public class LoadingTests extends TestMachine {
#Autowired
private AccountDao accountDao;
AppConfig.java
#Configuration
#PropertySource("classpath:application.properties")
#ComponentScan(basePackages = "company")
#EnableTransactionManagement
public class AppConfig {
#Bean
public AccountDao accountDao() {
return new AccountDao();
}
#Bean
public PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
#Bean
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(dataSource());
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
/*LOCAL*/
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/compamny");
dataSource.setUsername("root");
dataSource.setPassword("");
return dataSource;
}
#Bean(name = "sessionFactory")
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource());
sessionFactoryBean.setPackagesToScan("insynctive.model");
sessionFactoryBean.setHibernateProperties(hibProperties());
return sessionFactoryBean;
}
#Bean
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
private Properties hibProperties() {
Properties properties = new Properties();
properties.put(Environment.HBM2DDL_AUTO, "create");
properties.put(Environment.DIALECT, "org.hibernate.dialect.MySQLDialect");
properties.put(Environment.SHOW_SQL, true);
return properties;
}
}
SpringMVCConfiguration.java
#Configuration
#EnableWebMvc
#ComponentScan(basePackages="company.controller")
public class SpringMVCConfiguration extends WebMvcConfigurerAdapter {
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolverJSP = new InternalResourceViewResolver();
viewResolverJSP.setOrder(1);
viewResolverJSP.setViewClass(JstlView.class);
viewResolverJSP.setPrefix("views/jsp/");
viewResolverJSP.setSuffix(".jsp");
return viewResolverJSP;
}
}
SpringMVCInitializer.java
public class SpringMVCInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] {AppConfig.class, SpringMVCConfiguration.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
My autowired of AccountDao is returning null Why? but in my web application everything works good.
I Try lot of things like:
Create a new sessionFactory but doesn't work.
Used: classes ={AppConfig.class,SpringMVCConfig.class}.
Used: #ContextConfiguration(initializers = {SpringMVCInitializer.class}, loader=AnnotationConfigContextLoader.class) throw Type mismatch: cannot convert from Class to Class>
Used: #SpringApplicationConfiguration(classes = {SpringMVCInitializer.class})
I think you need to set initializers instead of classes on your LoadingTests class.
#ContextConfiguration(initializers = {SpringMVCInitializer.class}, loader=AnnotationConfigContextLoader.class)
Also please consider using constructor injection on your DAO.
Since you have #Repository you should include them with
#EnableJpaRepositories(basePackages="yourrepositories") at your config class
try adding
#WebAppConfiguration
before you test class.
The mere presence of #WebAppConfiguration on a test class ensures that a
WebApplicationContext will be loaded for the test using a default for
the path to the root of the web application.
I resolved this making a HibernateUtils to create a sessionFactory.