I'm facing some problems trying to setup JMS without spring boot, before I was using Spring and everything was working fine, but now I won't use it anymore, I'm using Google Guice for some reasons.
I configured that Jms class config to inject the things that it requires
org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.support.converter.MappingJackson2MessageConverter;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.converter.MessageType;
import org.springframework.util.ErrorHandler;
import org.springframework.util.backoff.FixedBackOff;
import javax.jms.ConnectionFactory;
#Configuration
#EnableJms
public class JmsConfig {
private static final String JMS_TYPE_ID_PROPERTY_NAME = "_type";
#Bean
public JmsListenerContainerFactory<?> jmsQueueFactory(
ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
log.info("JmsConfig.jmsQueueFactory - (TraceTest1)");
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
// This provides all Spring Boot's defaults to this factory, including message converter
configurer.configure(factory, connectionFactory);
factory.setErrorHandler(new JmsErrorHandler());
factory.setMessageConverter(jacksonJmsMessageConverter());
//retry indefinitely every 60 seconds
factory.setBackOff(new FixedBackOff(60000, FixedBackOff.UNLIMITED_ATTEMPTS));
return factory;
}
public static class JmsErrorHandler implements ErrorHandler {
private static final Logger log = LoggerFactory.getLogger(JmsErrorHandler.class);
#Override
public void handleError(Throwable t) {
log.error("JMS error", t);
}
}
#Bean
public MessageConverter jacksonJmsMessageConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
log.info("JmsConfig.jacksonJmsMessageConverter - (TraceTest2)");
converter.setTargetType(MessageType.TEXT);
converter.setTypeIdPropertyName(JMS_TYPE_ID_PROPERTY_NAME);
return converter;
}
}
The problems is, now that I'm not using Spring this class and respective beans does not initialize during the application start.
I have another method in another class, kind of a Main that has a "start method", I want to abstract this to call it there without spring but I could not find implementation of it manually using Guice, could you guys help me?
Thanks!
Related
This question already has an answer here:
Is it possible to set a bean name using annotations in Spring Framework?
(1 answer)
Closed 4 years ago.
I am testing out simple AOP use case in Spring but am getting the below error,
Exception in thread "main"
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
bean named 'bean1' is defined
Below are my source files,
DemoConfig.java
package com.luv2code.aopdemo;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import com.luv2code.aopdemo.aspect.MyDemoLoggingAspect;
import com.luv2code.aopdemo.dao.AccountDAO;
#Configuration
#EnableAspectJAutoProxy
#ComponentScan("com.luv2code.aopdemo")
public class DemoConfig {
#Bean
#Qualifier("bean1")
public AccountDAO accDao() {
return new AccountDAO();
}
#Bean
#Qualifier("bean2")
public MyDemoLoggingAspect myAscpect() {
return new MyDemoLoggingAspect();
}
}
MyDemoLoggingAspect.java
package com.luv2code.aopdemo.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
#Aspect
public class MyDemoLoggingAspect {
// this is where we add all of our related advices for logging
// let's start with an #Before advice
#Before("execution(** com.luv2code.aopdemo.dao.AccountDAO.addAccount(..))")
public void beforeAddAccountAdvice() {
System.out.println("\n=====>>> Executing #Before advice on addAccount()");
}
}
MainDemoApp.java
package com.luv2code.aopdemo;
import com.luv2code.aopdemo.dao.AccountDAO;
public class MainDemoApp {
public static void main(String[] args) {
// read spring config java class
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DemoConfig.class);
// get the bean from spring container
AccountDAO theAccountDAO = context.getBean("bean1", AccountDAO.class);
// call the business method
theAccountDAO.addAccount();
// do it again!
System.out.println("\nlet's call it again!\n");
// call the business method again
theAccountDAO.addAccount();
// close the context
context.close();
}
}
I have given my bean ID "bean1", even after that Spring is not able to find my bean in the context. Why am I getting this error and how to resolve this?
The #Qualifier tag is used with the #Autowired annotation.
What you need is
#Bean(name="bean1")
public AccountDAO accDao() {
return new AccountDAO();
}
RESOLVED - see answer.
I've looked through many similar questions and don't see a similar case right off. Certainly this isn't a unique situation and I'm just missing it?
Update A Spring example I found shows a priority property that may help here, but I have only found the XML example. Question expanded below.
Problem Summary
Two view resolvers appear to be conflicting in my SpringWebMVC application.
Problem Details
I'm work on a web app using Spring 4.0.3-RELEASE and have recently added Jackson to support returning Json from calls to a specific controller. This was working until I added an #Override to my SpringWebConfig for configureViewResolvers. Now my calls to my controller which was serving Json just return the template name which should call the Jackson mapper bean.
The big question
How can I make these two coexist? I have found that I can call:
registry.order(int)
and set it to 9 just to make sure it was last, but it still intercepted the jsonTemplate response from the controller. I don't see a way to set an order for the MappingJackson2JsonView bean. #Bean(order=0), for example, is invalid.
Things Tried
Redacting the ViewResolverRegistry, as expected, produces an error when trying to get mapped jsp views.
javax.servlet.ServletException: Could not resolve view with name 'someView' in servlet with name 'spring-mvc-dispatcher'
As noted in the question statement above, I've tried setting the order on the registry for the ViewResolverRegistry, but this did not help.
I also have tried adding the following to the MappingJackson2JsonView instance, view:
Properties props = new Properties();
props.put("order", 1);
view.setAttributes(props);
But as before, this doesn't prevent the ViewResolverRegistry from intercepting "jsonTemplate" before the Jackson mapper can process it.
I also have changed the load order of the configs in the AppInitializer, the code below has been updated to reflect the new load order, but this also did not help.
Reading through the Spring documentation a bit more, it appears that adding a ContentNegotiationConfigurer is going to be what I need to resolve this and I'm presently looking at how to get this to work in a way that preserves auto mapping the Model returned to the jsonTemplate view. Exapmles I've seen so far use a jsp as a view with specific properties called out, which defeats the purpose of using a Json Mapper.
Configuration
I have multiple config classes defined in my package com.mytest.config.
AppInitializer.java handles adding the *config classes to the context.
package com.mytest.config;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.request.RequestContextListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class AppInitializer implements WebApplicationInitializer {
private Logger logger = LoggerFactory.getLogger(AppInitializer.class);
#Override
public void onStartup(ServletContext container) throws ServletException {
try {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(JSONConfiguration.class);
ctx.register(SpringWebConfig.class);
ctx.setServletContext(container);
container.addListener(new ContextLoaderListener(ctx));
container.addListener(new RequestContextListener());
logger.info("Created AnnotationConfigWebApplicationContext");
ServletRegistration.Dynamic dispatcher = container.addServlet("spring-mvc-dispatcher", new DispatcherServlet(ctx));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
logger.info("DispatcherServlet added to AnnotationConfigWebApplicationContext");
} catch (Exception e) {
logger.error(e.getLocalizedMessage(), e);
}
}
}
SpringWebConfig.java is where I register the majority of my beans.
package com.mytest.config;
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.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#Configuration
#EnableWebMvc
#ComponentScan(basePackages={"com.mytest.controller","com.mytest.bean","com.mytest.model"})
#PropertySource(value={"classpath:application.properties"})
public class SpringWebConfig extends WebMvcConfigurerAdapter {
#Autowired
private Environment env;
private Logger logger = LoggerFactory.getLogger(SpringWebConfig.class);
// bunches of beans such as JdbcTemplate, DataSource... omitted for simplicity
#Override // apparent problem location -- needed for jsp resolving
public void configureViewResolvers(final ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/views/html/",".jsp");
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
logger.info("DefaultServletHandlerConfigurer enabled");
}
#Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(new com.honda.hrao.rid.config.RequestInterceptor());
logger.info("RequestInterceptor added to InterceptorRegistry");
}
}
JSONConfiguration.java is a controller I set up just for JSON.
package com.mytest.config;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.BeanNameViewResolver;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
#Configuration
#ComponentScan(basePackages = {"com.mytest.controller"})
#EnableWebMvc
public class JSONConfiguration {
private Logger logger = LoggerFactory.getLogger(JSONConfiguration.class);
#Bean // needed for JSON conversion of bean responses
public View jsonTemplate() {
logger.info("Registered MappingJackson2JsonView");
MappingJackson2JsonView view = new MappingJackson2JsonView();
Properties props = new Properties();
props.put("order", 1);
view.setAttributes(props);
view.setPrettyPrint(true);
return view;
}
#Bean
public ViewResolver viewResolver() {
logger.info("Starting ViewResolver bean");
return new BeanNameViewResolver();
}
}
Implementation
In my Controller, the following method should return JSON.
#Autowired
AppConstants appConstants;
#RequestMapping(method = RequestMethod.GET, value = "getAppConstants")
public String getAppConstants(Model model) {
model.addAttribute("AppConstants",appConstants);
if(appConstants==null) {
Logger.error("appConstants not autowired!!!");
return null;
}
return "jsonTemplate";
}
As mentioned above in Things Tried, this works fine if I remove the ViewResolverRegistry bean from the SpringWebConfig and if I leave the bean in place, the above controller method returns
404, /WEB-INF/views/html/jsonTemplate.jsp
The requested resource is not available.
-- which I understand. That's what the view resolver should do. How do I make my JSON calls bypass this?
It turns out there were only a couple of things missing. The first was to add the following annotation to the bean declaration for the mapper:
#Primary
So now, the bean setup looks like this.
#Bean // needed for JSON conversion of bean responses
#Primary
public View jsonTemplate() {
logger.info("Registered MappingJackson2JsonView");
MappingJackson2JsonView view = new MappingJackson2JsonView();
Properties props = new Properties();
props.put("order", 1);
view.setAttributes(props);
view.setPrettyPrint(true);
return view;
}
The second was to use a ContentNegotiationConfigurer. In my SpringWebConfig, I added the following:
public void configurationContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer
.ignoreUnknownPathExtensions(false)
.defaultContentType(MediaType.TEXT_HTML);
}
and changed my configureViewResolvers function as follows:
#Override // needed for jsp resolving
public void configureViewResolvers(final ViewResolverRegistry registry) {
MappingJackson2JsonView view = new MappingJackson2JsonView();
view.setPrettyPrint(true);
registry.enableContentNegotiation(view);
registry.jsp("/WEB-INF/views/html/",".jsp");
}
One clue was found in this example. The rest came from the Spring documentation.
I am trying to simple spring program that has a class named PersistenceConfig annotated with #Configuration
#Configuration
#PropertySource("classpath:application.properties")
public class PersistanceConfig {
#Value("${dbPassword}")
private String dbPassword;
// Set of Beans and Code
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
dataSource.setUrl("jdbc:sqlserver://localhost;databaseName=GovernmentPayment;integratedSecurity=false;");
dataSource.setUsername("sa");
dataSource.setPassword(dbPassword);
return dataSource;
}
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
When i run my program, the value dbPassword is always null but if i try to read the same value inside one my Controllers it reads the value without any issues.
I have tried autowiring Environment variable and using it instead of #Value but it didn't work either. (Spring didn't inject value to the Environment Variable)
I am using Spring 4
What is basically want is to externalize the database username and password in a separate property file.
i don't see any problem with given code.i wrote a simple unit test to your class to prove it works.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes=PersistanceConfig.class)
public class PersistanceConfigTest {
#Autowired
private DriverManagerDataSource dataSource;
private final String password = "mydbPassword";
#Test
public void testDriverManagerDataSourcePassword() {
System.out.println("dataSource Password :: " + dataSource.getPassword());
assertNotNull(dataSource);
assertTrue(password.equals(dataSource.getPassword()));
}
}
assuming you have application.properties in src/main/resources and dbPassword=mydbPassword is presented in that file.
Credit goes to Chad Darby
This is an issue with Spring versions.
If you are using Spring 4.2 and lower, you will need to add the code in marked with(**).
package com.luv2code.springdemo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
#Configuration
// #ComponentScan("com.luv2code.springdemo")
#PropertySource("classpath:sport.properties")
public class SportConfig {
// add support to resolve ${...} properties
**#Bean
public static PropertySourcesPlaceholderConfigurer
propertySourcesPlaceHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}**
// define bean for our sad fortune service
#Bean
public FortuneService sadFortuneService() {
return new SadFortuneService();
}
// define bean for our swim coach AND inject dependency
#Bean
public Coach swimCoach() {
SwimCoach mySwimCoach = new SwimCoach(sadFortuneService());
return mySwimCoach;
}
}
````
In Spring 4.3 and higher, they removed this requirement. As a result, you don't need this code.
I have solved this by moving that two annotations to the main file.
package com.luv2code.springdemo;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#ComponentScan(basePackages = "com.luv2code.springdemo.SportConfig")
public class SwimJavaConfigDemoApp {
public static void main(String[] args) {
// read spring config java class
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(SportConfig.class);
// get the bean from spring container
Coach theCoach = context.getBean("swimCoach", Coach.class);
// call a method on the bean
System.out.println(theCoach.getDailyWorkout());
// call method to get the daily fortune
System.out.println(theCoach.getDailyFortune());
// close the context
context.close();
}
}
Configure the main file.
Use component scan and specified the path to the cofig class.
Next, write some Bean's to the config file.
package com.luv2code.springdemo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
public class SportConfig {
// define a bean for sad fortune service
#Bean
public FortuneService sadFortuneService() {
return new SadFortuneService();
}
// define bean for our swim coach and inject dependency
#Bean
public Coach swimCoach() {
return new SwimCoach(sadFortuneService());
}
}
For futher learning : Component Scan.
I'm prototyping an application to test spring messaging features for a future application.
One thing I know we will need is to handle topics and queues from activemq in the same application. So, in the same bean I should have a method annotated by #JmsListener that will hear a queue and another that will hear a topic. Is that possible?
What is the simpler way to do that? I saw some answers to use topics with spring-jms like this one but in that case I imagine I will need to create two DefaultMessageListenerContainer, one for a topic and another for a queue. This is the best solution?
Is there any annotation approach for this issue?
Here is a full example of how to set up a second container factory for topics with spring boot:
JmsDemoApplication.java:
package net.lenthe;
import javax.jms.ConnectionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
#SpringBootApplication
public class JmsDemoApplication {
#Autowired
private ConnectionFactory connectionFactory;
#Bean(name = "topicJmsListenerContainerFactory")
public DefaultJmsListenerContainerFactory getTopicFactory() {
DefaultJmsListenerContainerFactory f = new DefaultJmsListenerContainerFactory();
f.setConnectionFactory(connectionFactory);
f.setSessionTransacted(true);
f.setPubSubDomain(true);
return f;
}
public static void main(String[] args) {
SpringApplication.run(JmsDemoApplication.class, args);
}
}
MessageListenerBean.java:
package net.lenthe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
#Component
public class MessageListenerBean {
private Logger logger = LoggerFactory.getLogger(this.getClass());
#JmsListener(destination = "myMessageTopic", containerFactory = "topicJmsListenerContainerFactory")
public void processTopicMessage(String content) {
logger.info("Received topic message. Content is " + content);
}
#JmsListener(destination = "myMessageQueue")
public void processQueueMessage(String content) {
logger.info("Received queue message. Content is " + content);
}
}
The framework will take care of creating a container for each #JmsListener; you just need to tell it which container factory to use via the containerFactory property.
I'm trying to add security to my Spring 3.2.8-based pure Java-configured application. I'm following the instructions http://docs.spring.io/spring-security/site/docs/3.2.2.RELEASE/reference/htmlsingle/#jc
I've completed section 3.1, and the documentation says at this point that every URL should require authentication, but none do (at least, I can load every URL). It says it creates a Servlet filter, etc.
It's evident that by itself, that WebSecurityConfigurerAdapter subclass is not enough. So I look at section 3.1.1, which says the next step is to register the springSecurityFilterChain with the WAR, and goes on to say how in a Servlet 3+ environment, I need to subclass AbstractSecurityWebApplicationInitializer. But I'm already subclassing AbstractAnnotationConfigDispatcherServletInitializer. Am I supposed to have one of each? There is some discussion of ordering in the AbstractSecurityWebApplicationInitializer JavaDoc, implying I should have more than one initializer class.
In all this, it also said to add the WebSecurityConfigurerAdapter subclass to getRootConfigClasses() (although the example doesn't show the "AppConfig" that the other Spring getting started docs have you create; also, this alone wasn't enough).
So I tried adding another initializer class. All my other classes are public static inner classes of my AbstractAnnotationConfigDispatcherServletInitializer subclass, so I put another in there to be the AbstractSecurityWebApplicationInitializer subclass (rather than creating a separate .java file).
WARNING com.caucho.server.webapp.WebApp setConfigException: java.lang.UnsupportedOperationException: unimplemented
at com.caucho.server.webapp.ServletContextImpl.setSessionTrackingModes(ServletContextImpl.java:552)
at org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer.onStartup(AbstractSecurityWebApplicationInitializer.java:120)
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:174)
at com.caucho.server.webapp.WebApp.callInitializer(WebApp.java:3471)
at com.caucho.server.webapp.WebApp.callInitializers(WebApp.java:3439)
at com.caucho.server.webapp.WebApp.startImpl(WebApp.java:3661)
at com.caucho.server.webapp.WebApp$StartupTask.run(WebApp.java:5196)
at com.caucho.env.thread2.ResinThread2.runTasks(ResinThread2.java:173)
at com.caucho.env.thread2.ResinThread2.run(ResinThread2.java:118)
I tried adding ordering to no avail. My entire config:
package com.latencyzero.satdb.web;
//
// Java Imports
//
import java.util.Properties;
import java.util.ResourceBundle;
import javax.naming.InitialContext;
import javax.servlet.ServletContext;
import javax.sql.DataSource;
//
// Library Imports
//
import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.xml.DOMConfigurator;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
//
// Project Imports
//
/**
There are still some things that get configured in the container. This app
was developed using Resin. Things configured in resin's XML config for this
app include the data source, error page, key store password for Apple
Push Notifications (which should move to the DB).
*/
public
class
WebappInitializer
extends
org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer
{
#Override
protected
Class<?>[]
getRootConfigClasses()
{
Class<?>[] classes = { AppConfig.class, SecurityConfig.class };
return classes;
}
#Override
protected
Class<?>[]
getServletConfigClasses()
{
Class<?>[] classes = { WebConfig.class };
return classes;
}
#Override
protected
java.lang.String[]
getServletMappings()
{
String[] mappings = { "/" };
return mappings;
}
#Override
protected
javax.servlet.Filter[]
getServletFilters()
{
return new javax.servlet.Filter[]
{
new org.springframework.orm.hibernate3.support.OpenSessionInViewFilter(),
};
}
/** *******************************************************************************************************************
App context configuration.
Hibernate config (data access, transactions, data model).
*/
#Configuration
#EnableAsync
#EnableTransactionManagement
#ComponentScan(basePackages = { "com.mymodelanddao", })
public
static
class
AppConfig
{
#Bean
public
org.springframework.jndi.JndiObjectFactoryBean
dataSource()
{
org.springframework.jndi.JndiObjectFactoryBean bean = new org.springframework.jndi.JndiObjectFactoryBean();
bean.setJndiName("java:comp/env/jdbc/db");
return bean;
}
#Bean
public
org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean
sessionFactory()
{
DataSource dataSource = (DataSource) dataSource().getObject();
org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean bean = new org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean();
bean.setDataSource(dataSource);
// TODO: Do we need to scan this, since it's done as part of #ComponentScan?
bean.setPackagesToScan(new String[] {"com.latencyzero.satdb.model"});
Properties props = new Properties();
props.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
props.setProperty("hibernate.cache.provider_class", "org.hibernate.cache.NoCacheProvider");
props.setProperty("hibernate.jdbc.batch_size", "200");
props.setProperty("hibernate.show_sql", "false");
props.setProperty("hibernate.format_sql", "true");
props.setProperty("hibernate.use_sql_comments", "false");
props.setProperty("hibernate.generate_statistics", "true");
bean.setHibernateProperties(props);
return bean;
}
#Bean
public
PlatformTransactionManager
transactionManager()
{
SessionFactory sf = sessionFactory().getObject();
org.springframework.orm.hibernate3.HibernateTransactionManager bean = new org.springframework.orm.hibernate3.HibernateTransactionManager();
bean.setSessionFactory(sf);
return bean;
}
private static Logger sLogger = Logger.getLogger(AppConfig.class);
}
/** *******************************************************************************************************************
Web context configuration.
*/
#Configuration
#EnableWebMvc
#ComponentScan(basePackageClasses = { com.mycontrollerclasses })
public
static
class
WebConfig
extends
org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
{
#Bean
public
InternalResourceViewResolver
getInternalResourceViewResolver()
{
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
return resolver;
}
#Bean
public
org.springframework.web.multipart.commons.CommonsMultipartResolver
multipartResolver()
{
return new org.springframework.web.multipart.commons.CommonsMultipartResolver();
}
#Override
public
void
addResourceHandlers(ResourceHandlerRegistry inRegistry)
{
inRegistry.addResourceHandler("/assets/**").addResourceLocations("/assets/").setCachePeriod(31556926);
inRegistry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(31556926);
inRegistry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(31556926);
}
private static Logger sLogger = Logger.getLogger(WebConfig.class);
}
/** *******************************************************************************************************************
Security configuration.
*/
#Configuration
#EnableWebMvcSecurity
public
static
class
SecurityConfig
extends
org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
{
#Autowired
public
void
configureGlobal(AuthenticationManagerBuilder inAuth)
throws
Exception
{
sLogger.warn("configureGlobal =================================================");
inAuth
.inMemoryAuthentication()
.withUser("user")
.password("password")
.roles("USER");
}
private static Logger sLogger = Logger.getLogger(SecurityConfig.class);
}
public
static
class
SecurityWebApplicationInitializer
extends
org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer
{
}
}
According to https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#abstractsecuritywebapplicationinitializer-with-spring-mvc, you have to introduce a second WebApplicationInitializer, typically derivating from AbstractSecurityWebApplicationInitializer
This second WebApplicationInitializer would register property the springFilterChain
Answering using 5.0.6 Spring Security version:
#EnableWebSecurity already contains #Configuration, therefore
specifying both is redundant
You are indeed required to have a second appinitializer, which extends AbstractSecurityWebApplicationInitializer. Your one seems OK
Your getRootConfigClasses is also OK.
You really should register SecurityConfig.class there.
Your thoughts and configuration seems right, except I'm not really sure if keeping your SecurityWebApplicationInitializer as static inner class allows Spring to find it. Maybe it can be a problem. I did all the configuration acc to above mentioned instruction and everything is working like a charm, redirecting me to "/login" page.