I'm in the process of converting XML based configuration for a Spring Java Web project to JavaConfig.
I'm using JPA. So I created an additional JavaConfig class with the necessary configuration. But the JPA configuration fails for some reason.
Here is my [web.xml][1]
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<!-- Configuration locations must consist of one or more comma- or space-delimited
fully-qualified #Configuration classes. Fully-qualified packages may also be
specified for component-scanning -->
<!-- <context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.my.contoso.spring.contosoJPA</param-value>
</context-param>-->
<!-- Bootstrap the root application context as usual using ContextLoaderListener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Declare a Spring MVC DispatcherServlet as usual -->
<servlet>
<servlet-name>restservices</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
instead of the default XmlWebApplicationContext -->
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<!-- Again, config locations must consist of one or more comma- or space-delimited
and fully-qualified #Configuration classes -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.my.contoso.spring.contosoConfig</param-value>
</init-param>
</servlet>
<!--
This Servlet mapping means that this Servlet will handle all incoming requests
-->
<servlet-mapping>
<servlet-name>restservices</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- for CORS -->
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
<init-param>
<param-name>cors.supportedMethods</param-name>
<param-value>GET, HEAD, POST, PUT, DELETE, OPTIONS</param-value>
</init-param>
<init-param>
<param-name>cors.supportedHeaders</param-name>
<param-value>Content-Type, X-Requested-With, Origin, Accept</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- End for CORS -->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<filter>
<filter-name>OpenEntityManagerFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
<init-param>
<param-name>entityManagerFactoryBeanName</param-name>
<param-value>entityManagerFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>OpenEntityManagerFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- <resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/contosoDS</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>-->
</web-app>
Here is my primary [JavaConfig class][2]
#Configuration
#EnableWebMvc
//#ImportResource("contoso-jpa.xml") //Import any existing xml context files
#Import(contosoJPA.class)
//#EnableTransactionManagement //substitute for <tx:annotation-driven/>
#ComponentScan({"com.my.contoso.webservices.rest", "com.my.contoso.services,com.my.contoso.dao"})
public class contosoConfig {
}
And Here's the JavaConfig class with [JPA config][3]
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories //(basePackages = { "com.my.contoso.domain" })
public class contosoJPA {
#Bean
public DataSource dataSource() {
// return new EmbeddedDatabaseBuilder().setType(H2).build();
DriverManagerDataSource ds = new DriverManagerDataSource();
try {
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUsername("root");
ds.setPassword("");
ds.setUrl("jdbc:mysql://localhost:3306/contosodb");
} catch (Exception e) {
// logger.error(e.getMessage());
System.out.println(e);
}
return ds;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) {
LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(dataSource);
lef.setJpaVendorAdapter(jpaVendorAdapter);
lef.setPackagesToScan("com.my.contoso.domain");
lef.setPersistenceUnitName("contosoPU");
return lef;
}
#Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setShowSql(false);
hibernateJpaVendorAdapter.setGenerateDdl(true);
hibernateJpaVendorAdapter.setDatabase(Database.MYSQL);
// hibernateJpaVendorAdapter.setDatabase(Database.H2);
return hibernateJpaVendorAdapter;
}
#Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager();
}
}
Full Stack Trace:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:570)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1108)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:278)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1121)
at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.lookupEntityManagerFactory(OpenEntityManagerInViewFilter.java:222)
at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.lookupEntityManagerFactory(OpenEntityManagerInViewFilter.java:205)
at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:152)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:179)
at com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:241)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2430)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2419)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:570)
'entityManagerFactory' is declared in the [web.xml][1]. The error says that a bean with such name doesn't exist. But I did include it in the [JPA config][3] file. So I'm guessing that the beans in the JPA javaConfig file are not getting picked up. Wondering where the configuration is failing.
Why did you comment out
<!-- Configuration locations must consist of one or more comma- or space-delimited
fully-qualified #Configuration classes. Fully-qualified packages may also be
specified for component-scanning -->
<!-- <context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.uhsarp.billrive.spring.BillriveJPA</param-value>
</context-param>-->
?
It seems to me like that root context should be loaded and made available to the whole application through the ContextLoaderListener. That context-param needs to be available so that the root context has a source from which to load bean definitions.
i would try to remove parameters and call bean methods manually:
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(dataSource());
lef.setJpaVendorAdapter(jpaVendorAdapter());
lef.setPackagesToScan("com.my.contoso.domain");
lef.setPersistenceUnitName("contosoPU");
return lef;
}
then
try to debug/sout if spring get to any method from this configuration class.
Maybe mixing web.xml configuration with java config is not the best idea? Did you consider to migrate it? :)
Related
I'm trying to enable Spring Security in my Spring MVC application which serves some REST web services (Java 8). The problem I have is whatever I do the auth just doesn't work at all. I can access my REST endpoints without any credentials. I use this manual: https://docs.spring.io/spring-security/site/docs/5.0.7.RELEASE/reference/htmlsingle/
Git repo with full code of my app is here: https://github.com/SP8EBC/MKS_JG_ONLINE
SecurityConfig.java looks as follows
#EnableWebSecurity
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser(Secret.user).password("{noop}" + Secret.password).roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// http
// .csrf()
// .disable()
// .authorizeRequests().antMatchers("/**").permitAll()
// .anyRequest().authenticated()
// .and()
// .httpBasic()
// .realmName("test")
// .authenticationEntryPoint(new CustomAuthenticationEntryPoint());
http.authorizeRequests().anyRequest().denyAll();
}
}
AppConfig.java
#Configuration
#Import(SecurityConfig.class)
#EnableWebMvc
#EnableSpringDataWebSupport
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = {"pl.jeleniagora.mks.dao.repository"})
#ComponentScan("pl.jeleniagora.mks")
public class AppConfig{
// beans and app config
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>MKS_JG_ONLINE</display-name>
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>pl.jeleniagora.mks.ws.config</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>pl.jeleniagora.mks.ws.controllers</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file />
</welcome-file-list>
</web-app>
When I start the Tomcat 8.5 in debug mode I see that the SecurityConfig loads (execution stops at breakpoint in configure and configureGlobal). What I'm doing wrong?
Spring Security requires, next to the security configuration, a servlet filter to be registered.
Add the following to your web.xml (explained here).
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
This will add the filter and will be applied to all requests.
However as you are using a recent servlet container I would suggest to ditch the web.xml and create 2 java classes to do the bootstrapping. (See also here).
First bootstrap your application
public class MvcWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
public Class<?>[] getServletConfigClasses() {
return new Class[] { WebConfig.class }; // or whatever it is called or return `null`
}
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { AppConfig.class };
}
}
Then add the one that bootstraps/configures Spring Security filter
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer { }
Now everything is configured in Java and you can do without your web.xml.
Okay I've done a lot of googling and I can't seem to find a clear answer. Let's keep it as simple as possible. I have a web.xml file
<listener>
<listener-class>A</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:springcontexts/*.xml</param-value>
</context-param>
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<servlet>
<servlet-name>spring-ws</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:wsspringcontexts/*.xml</param-value>
</init-param>
</servlet>
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring_mvc_contexts/*.xml</param-value>
</init-param>
</servlet>
I think I know how to migrate this to Spring Boot ...
#SpringBootApplication(exclude = DispatcherServletAutoConfiguration.class)
#ImportResource("classpath*:springcontexts/*.xml")
public class Application
{
public static void main(String[] args)
{
SpringApplication.run(Application.class, args);
}
}
Somewhere in a sub-package...
#Configuration
#EnableWebMvc
public class SpringMVCConfiguration
{
#Bean
public ServletRegistrationBean mvc()
{
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.setConfigLocation("classpath*:spring_mvc_contexts/*.xml");
// the dispatcher servlet should automatically add the root context
// as a parent to the dispatcher servlet's applicationContext
DispatcherServlet dispatcherServlet = new DispatcherServlet(applicationContext);
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(dispatcherServlet, "/spring/*");
servletRegistrationBean.setName("DispatcherServlet");
return servletRegistrationBean;
}
}
...and we do the above again for the other Servlet
My first problem is how to add the listener "A" to Spring Boot and ensure it runs before the root application is refreshed? Some beans that get configured require some static fields to be setup (legacy code), and this setup is done in listener "A". This works fine when deployed as a standard war using the above web.xml
In addition does the above Spring Boot setup look correct?
Why not put your legacy initialisation in a postConstruct method on a bean ?
Failing that you can add a listener that implements
ApplicationListener<ContextRefreshedEvent>
and overrides
public void onApplicationEvent(final ContextRefreshedEvent event)
Does your Spring Boot setup look OK ? Difficult to tell, though I'd let Spring Boot autoconfigure things like the dispatcher servlet for you and get rid of any XML config if at all possible.
I need to Autowire a service class annotated with #Service annotation in my session listener class as I need to perform some DB operation on session destroyed method. I am not able to autowire the service class as I have added the listener in my web.xml and it is no longer spring managed. I have tried several options(workarounds) like getting a bean from application context via servlet context but I am not getting any beans in that way.
Following are my classes:-
MyService:
#Service
#Transactional
public class FxTransactionService{
//some autowirings
public void performDBoperation(Long id)
{
//business logic
}
}
Session Listener:
public class SessionHandler implements HttpSessionListener {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
#Autowired
private MyService myService;
#Override
public void sessionCreated(HttpSessionEvent arg0) {
System.out.println("Session created");
ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(arg0.getSession()
.getServletContext());
System.out.println(Arrays.toString(context.getBeanDefinitionNames()));
//This gives me empty list
}
#Override
public void sessionDestroyed(HttpSessionEvent arg0) {
Long id = (Long) arg0.getSession().getAttribute("Id");
myService.performDBoperation(id);
}
}
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>com.abc.controller.SessionHandler</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j.properties</param-value>
</context-param>
<filter>
<filter-name>preAuthHeaderAdditionFilter</filter-name>
<filter-class>com.abc.filter.PreAuthHeaderAdditionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>preAuthHeaderAdditionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- <filter> <filter-name>openEntityManagerInViewFilter</filter-name> <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter> <filter-mapping> <filter-name>openEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern> </filter-mapping> -->
</web-app>
First install the Spring listener ContextLoaderListener.
In your own listener you can access the context using WebApplicationContextUtils.
It is not autowiring though, you have to fetch the required bean/service yourself.
I have a question about spring context. My application's using spring and spring scheduler.
In web.xml, i declared:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
My question is:
If I declared org.springframework.web.context.ContextLoaderListener in web.xml, the scheduler will run twice, all beans are duplicate, and App start-up time about 160 seconds.
If I remove org.springframework.web.context.ContextLoaderListener,
spring throws exception: No WebApplicationContext found: no ContextLoaderListener registered. And App start-up time reduce to 80 seconds.
How can i solve it? Thanks all!
Thanks #M.Deinum, but i don't understand your idea.
Here is my web.xml:
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.htc.epos.api.bootstrap</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>webapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
com.htc.epos.api.bootstrap.WebAppConfig
com.htc.epos.api.bootstrap.AppConfig
</param-value>
</init-param>
</servlet>
Think #M.Deinum is right; split your beans via what is remoting and what is normal. I do this in my web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/spring/root-context.xml</param-value>
</context-param>
<servlet>
<servlet-name>remoting</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/spring/remoting-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>remoting</servlet-name>
<url-pattern>/remoting/*</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
root-context.xml contains all my normal beans (services, helpers, calculator, jms listeners, scheduled tasks, etc).
remoting-servlet.xml only specifies those services that need to be exposed via the HttpInvokerServiceExporter. There are no imports or links to beans defined in the root, other than things like ref="historyWebService" for the exporter.
From what I understand, you end up with 2 application context: 1 root and 1 remoting. The remoting one inherits all the beans from the root so you don't declare or instantiate beans twice (i think)!!! I certain don't appear to have duplicate beans produced (i.e. 2 task, 2 jms listeners, etc).
I have 2 file config:
1. AppConfig:
#Configuration
#EnableScheduling
#EnableTransactionManagement
#EnableJpaRepositories("com.test.api.repository")
#PropertySource("classpath:application.properties")
public class AppConfig {
...............
}
2. WebInitializer
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[0];
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebAppConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = {"com.test.api"})
public static class WebAppConfig extends WebMvcConfigurerAdapter {
...................
}
}
In WebAppConfig, if I change #ComponentScan(basePackages = {"com.test.api"}) to web package #ComponentScan(basePackages = {"com.test.api.web"}), so spring bean's not duplicate and scheduler not run twice. But sometime it throw exception:
error: org.hibernate.LazyInitializationException: could not initialize proxy - no Session
I have an xml configuration of spring as below:
<bean id="processor"
class="org.springframework.security.saml.processor.SAMLProcessorImpl">
<constructor-arg>
<list>
<ref bean="redirectBinding" />
<ref bean="postBinding" />
<ref bean="artifactBinding" />
<ref bean="soapBinding" />
<ref bean="paosBinding" />
</list>
</constructor-arg>
</bean>
I also have another Java Configuration of Spring as below:
#ImportResource({ "classpath:security/samlMetadata.xml" })
#Configuration
public class SecConfig{
#Autowired
private SAMLProcessorImpl processor;
#Bean(name ="webSSOProfileConsumer")
public WebSSOProfileConsumer webSSOProfileConsumer(){
WebSSOProfileConsumerImpl webSSOProfileConsumerImpl = new WebSSOProfileConsumerImpl();
try {
webSSOProfileConsumerImpl.setProcessor(processor);
webSSOProfileConsumerImpl.afterPropertiesSet();
}
catch (Exception e) {
e.printStackTrace();
}
return webSSOProfileConsumerImpl;
}
}
I get the processor bean as null, please help me if I am missing some basic thing while autowiring.
EDIT
Here is the relevant part of web.xml The only thing I am skipping is welcome-file-list
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.config.WebConfig
</param-value>
</context-param>
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>production</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>security</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>security</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>filterChainProxy</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>filterChainProxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
EDIT2
#Configuration
#ImportResource({ "classpath:security/samlMetadata.xml" })
#Import({SecureConfig.class})
#Profile("production")
#ComponentScan(basePackages = "com.config")
public class WebConfig extends WebMvcConfigurationSupport {
#Bean(name = "viewResolver")
public InternalResourceViewResolver viewResolver() throws Exception {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
I am sorry I didn't add this class earlier.