Spring seems to resolve and create the autowired objects just fine on boot up. But when I try to access them they come back as null. Anyone have any guesses on what might be going on?
Also XML info is blank as I'm only allowed one hyperlink...
<beans xmlns=""
xmlns:xsi=""
xmlns:p=""
xmlns:mvc=""
xmlns:context=""
xsi:schemaLocation="...only allowed one hyperlink" default-autowire="byName">
<mvc:annotation-driven />
<context:component-scan base-package="com.blah.controller"/>
<context:component-scan base-package="com.blah.*.service"/>
<context:component-scan base-package="com.blah.*.dao"/>
<context:annotation-config />
public class AuthFilter extends UsernamePasswordAuthenticationFilter {
#Autowired
private ProfileService profileService;
//.... Do more stuff below that shows profileService coming back as null.
}
I was able to use a debugger to show that the object was being initialized. I can paste my logs here if you guys want but that's a lot to back edit :).
Adding a bit to this where authfilter is defined:
<b:bean id="authenticationFilter" class="com.blah.auth.AuthFilter">
<b:property name="authenticationManager" ref="authenticationManager" />
<b:property name="filterProcessesUrl" value="/login/validate" />
<b:property name="usernameParameter" value="username" />
<b:property name="passwordParameter" value="password" />
<b:property name="authenticationSuccessHandler" ref="authSuccessHandler" />
<b:property name="authenticationFailureHandler" ref="authFailureHandler" />
</b:bean>
The component scan is in springapp-servlet.xml
I've created a pastebin of the boot logs. No dice with moving the component scan. http://pastebin.com/ttC5MPnQ
see if the there is something suspicious in the logs
it appears to me that AuthFilter is not a spring bean - either map it in the xml config, or annotate it with #Component.
remove default-autowire="byName" if you don't have a compelling reason to have it set so.
make sure you use that filter from within the context, and not instantiating it yourself.
make sure you are not referring to a bean defined in a parent context (for example - a bean defined in applicationContext.xml can't access a bean defined in dispatcher-servlet.xml)
place a component-scan in the applicationContext.xml (not the servlet one). (You can retain the one in the servlet xml but limit it to web packages only)
Related
I am using the decorator patter in my application and would like to configure it in xml spring configuration.
Lets say I have a class someService and a decorator called someServiceDecorator. Both services have multiple dependencies.
I tried this:
<beans:bean id="someService" autowire="constructor" class="com.my.someService" />
<beans:bean id="someServiceDecorator" autowire="constructor" primary="true" class="com.my.someServiceDecorator" />
Without success. I think it is strange I can't find any examples of the decorator pattern for spring with xml configuration.
Actually, I just tried this and this worked.
<beans:bean id="someServiceDecorator" autowire="constructor" class="com.my.someServiceDecorator">
<constructor-arg>
<beans:bean autowire="constructor" class="com.my.someService" />
</constructor-arg>
</beans:bean>
I am new to spring. Admins of my spring based web app want to configure settings from the web interface, so users can authenticate against LDAP server with their company username and password.
Change in LDAP settings should be possible without restarting the application. This might happen during a 'migration' or whatever reason. I have a couple beans, which need to be refreshed after the admin saves new settings for the LDAP server:
<bean id="ldapServer" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg>
<list>
<value>${ldap.url1}</value>
...
</list>
</constructor-arg>
<constructor-arg value="${ldap.basedn}"</constructor-arg>
<property name="referral" value="${ldap.referral}" />
<property name="baseEnvironmentProperties">...</property>
<property name="userDn" value="${ldap.username}" />
<property name="password" value="${ldap.password}" />
</bean>
I am using Springframework 3.1.2. The problem is, there are constructor arguments, which I want to change and not affect other running jobs. I tried playing with Scoped proxy, but not to much success yet:
<bean id="ldapServer" scope="prototype" ...>
<aop:scoped-proxy/>
I was successful though to get ldapServer to reinstantiate, when using prototype scope by running this piece of code:
#Controller
public class LDAPSettingsController implements ApplicationContextAware {
public ModelAndView handleRequest(...) {
DefaultSpringSecurityContextSource ldap;
ldap = context.getParentBeanFactor().getBean("ldapServer");
System.out.println(ldap.hashCode());
return new ModelAndView(new RedirectView('login.jsp'));
}
...
}
Are scopes and proxies here the way to go, or is the another mechanism in Spring to reflect configuration changes into a running program instance?
UPDATE: Clear up the question.
UPDATE: The root problem with the AOP proxies was following root exception:
java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
What worked was adding proxy-target-class="false" attribute to the <aop:scoped-proxy/> tag. I created a new scope, which works better than prototype - It destroys beans on settings update. Now I have this in my beans.xml:
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="ldap">
<ref bean="ldapScope" />
</entry>
</map>
</property>
</bean>
<bean id="ldapScope" class="com.myapp.SettingsScope" />
<bean id="ldapServer" scope="ldap" ...>
<aop:scoped-proxy proxy-target-class="false"/>
<constructor-args>
<list><value>${ldap.url1}</value> .. </list>
</constructor-args>
...
</bean>
I also have a controller for LDAP settings into which I inject ldapScope and I call a method which destroys current life-cycle objects and starts a new life-cycle every time, user presses the apply button.
PS: Not sure if I handle the life-cycle "re-start" in the right way - people my way to look for auto-start beans and start them after such event happens (i.e.: Setting -> Apply)
It is the part of servlet-context relating to internalisation.
<context:component-scan base-package="com.project.controllers" />
<interceptors>
<beans:bean
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"
p:paramName="lang" />
<beans:bean
class="org.springframework.web.servlet.theme.ThemeChangeInterceptor" />
</interceptors>
<!-- i18n -->
<beans:bean
class="org.springframework.context.support.ReloadableResourceBundleMessageSource"
id="messageSource" p:basenames="WEB-INF/i18n/messages, WEB-INF/i18n/application"
p:fallbackToSystemLocale="false" />
<beans:bean class="org.springframework.web.servlet.i18n.CookieLocaleResolver"
id="localResolver" p:cookieName="locale" />
The root-context:
<context:component-scan base-package="com.project"/>
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="en" />
</bean>
If I try to get message within jsp page or within controllers package everything is ok:
messageSource.getMessage("message.code", new Object[] {}, locale)
But it does not work out of the package defined in servlet-context, though messageSource bean is autowired.
Does it mean that root-context has default messageSource and in servlet-context it is overriden only for particular package?
Configuration defined in ServletContext for a specific controller always overrides the configuration of the rootContext. Also it is private to the root context.
The configuration you put in the servlet context is specific to that particular servlet/controller. If you need a global functionality for internationalization you should define the messageSource bean in the root Context.
When an ApplicationContext is loaded, it automatically searches for a MessageSource bean defined in the context. The bean must have the name messageSource. If such a bean is found, all calls to the preceding methods are delegated to the message source. If no message source is found, the ApplicationContext attempts to find a parent containing a bean with the same name. If it does, it uses that bean as the MessageSource. If the ApplicationContext cannot find any source for messages, an empty DelegatingMessageSource is instantiated in order to be able to accept calls to the methods defined above.
In my Spring-Module.xml I have two beans:
<bean id="two_num" class="main.java.com.shen.Generator">
<property name="length" value="8" />
<property name="categories" value="3" />
...
</bean>
<bean id="six_num" class="main.java.com.shen.Generator">
<property name="length" value="6" />
<property name="categories" value="1" />
<property name="numeric" value="numeric" />
...
</bean>
And I instantiate my class like so:
ApplicationContext context = new ClassPathXmlApplicationContext("Spring-Module.xml");
Generator obj = (Generator) context.getBean("two_num");
For some reasons, java is always instantiating my second bean despite me explicitly saying that I want the bean "two_num". If I were to flip the order around, and have "six_num"'s bean above "two_num", it would get the bottom bean. :| What's going on? I'm so confused. Is my method for selecting a specific bean wrong?
EDIT: after adding one more bean to it this is what I get when I run my program:
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#e949f69: defining beans [two_num,six_num,four_num]; root of factory hierarchy
And as expected, when I call a print method in my class, I can see that the current object is instantiated with the information dicated in four_num, and not "two_num"
Certainly remove static modifiers on your fields, as already suggested.
Also, if you want 'singletons' modify your XML:
<bean id="two_num" class="main.java.com.shen.Generator" scope="singleton">
<property name="length" value="8" />
<property name="categories" value="3" />
...
</bean>
So you'll only get a single instance of each bean. You'll still get multiple instances of Generator, but only one per bean.
Based on comments, I can only assume that the Generator class looks something like this
public class Generator {
private static length;
private static categories;
//getters/setters
}
Given that i dont have a full class to work with, i can only recommend removing the static modifier as it would contradict the way you want to use the class.
I am attempting to use Apache Shiro with Spring and MongoDB. I am using Spring Data Repositories which are autowired. I have created my own custom realm for Shiro which uses a Spring Data repository to talk to Mongo:
public class PlatformRealm extends AuthorizingRealm {
#Autowired(required = true)
protected UserRepository userRepository = null;
#Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
...
}
}
The problem I'm seeing is the userRepository isn't being autowired. I get the following line in my console output referring to the PlatformRealm:
INFO org.springframework.web.context.support.XmlWebApplicationContext - Bean 'platformRealm' of type [class com.resonance.platform.core.security.PlatformRealm] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
This is because of the Apache Shiro ShiroFilterFactoryBean. What is happening is this bean and all of its dependencies are being loaded up immediately when the container is started. It doesn't wait for my persistence beans to be initialized prior to resolving dependencies. This causes the repository reference to be null.
The following bean configurations are loaded via the contextConfigLocation parameter:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/web-platform-persistence.xml,
/WEB-INF/web-platform-services.xml
</param-value>
</context-param>
Services bean configuration:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<bean id="userSession"
class="com.resonance.platform.web.core.services.ShiroUserSessionService" />
<!-- Shiro (Security) -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login" />
<property name="successUrl" value="/" />
<!-- The 'filters' property is not necessary since any declared javax.servlet.Filter
bean -->
<!-- defined will be automatically acquired and available via its beanName
in chain -->
<!-- definitions, but you can perform instance overrides or name aliases
here if you like: -->
<!-- <property name="filters"> <util:map> <entry key="anAlias" value-ref="someFilter"/>
</util:map> </property> -->
<property name="filterChainDefinitions">
<value>
# some example chain definitions:
/admin/** = passThruFilter, roles[admin]
/** = passThruFilter
</value>
</property>
</bean>
<bean id="passThruFilter"
class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter" />
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- Single realm app. If you have multiple realms, use the 'realms' property
instead. -->
<property name="realm" ref="platformRealm" />
<!-- By default the servlet container sessions will be used. Uncomment
this line to use shiro's native sessions (see the JavaDoc for more): -->
<!-- <property name="sessionMode" value="native"/> -->
</bean>
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor" />
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
<!-- Define the Shiro Realm implementation you want to use to connect to
your back-end -->
<!-- security datasource: -->
<bean id="platformRealm" class="com.resonance.platform.core.security.PlatformRealm" />
Persistence bean config:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<mongo:mongo id="mongo" />
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg ref="mongo" />
<constructor-arg value="platform" />
<property name="writeConcern">
<util:constant static-field="com.mongodb.WriteConcern.SAFE" ></util:constant>
</property>
</bean>
<mongo:repositories base-package="com.resonance.platform.core.data.repositories" />
User Repository:
package com.resonance.platform.core.data.repositories;
import org.bson.types.ObjectId;
import org.springframework.data.repository.CrudRepository;
import com.resonance.platform.core.entities.User;
/**
* A repository used to manage User entities.
* #author Kyle
*/
public interface UserRepository extends CrudRepository<User, ObjectId> {
/**
* Gets a user by the specified login.
* #param login
* #return
*/
User getByLogin(String login);
}
My question is, how can I get the userRepository dependency to resolved properly? I understand that the ShiroFilterFactoryBean has to be initialized before the other dependencies and whatnot, but there must be a way to get the userRepository dependency to be resolved.
EDIT: Added User Repository code.
I am running into the same problem described here.
I am noticing two spring factories.
from the dispacher-servlet.xml which loads #Service #Repository classes due to component-scan defined at an base package level so I can #Autowire Service class into Controller.
from application context doesn't seem to #Autowire classes marked as #Service because they are not loaded.
If I understand you right you should be able to create a subclass of ShiroFilterFactoryBean which implements org.springframework.beans.factory.InitializingBean. In InitializingBean.afterPropertiesSet() you would then add some code that gets the UserRepository and sets it to that field. Not the most elegant solution, but this looks like an exceptional case.
I've had this problem too. It has something to do with the order of bean initialization in the Spring container. The workaround is not to autowire the repository but have your realm implement ApplicationContextAware and get the needed beans straight from the context. It's not elegant, but it'll work.
I am not too sure if this is helpful, but you may check this question from me for an alternative solution.
But, the core issue probably still stays open.
Concrete problem explanation taken from ShiroFilterFactoryBean-and-a-spring-data-mongodb-realm:
The problem is that spring-data-mongodb requires a spring
ApplicationEventMulticaster to have been initialised before it can be
used.
ShiroFilterFactoryBean is a beanPostProcessor, and as such, during
initialisation, spring attempts to configure its realms(and hence my
realm and spring data mongo based userDao). it fails because
ApplicationEventMulticaster has not yet been created.
After I've tried several suggested ways to solve this problem, like the InitializingBean, ApplicationContextAware or BeanPostProcessor interfaces (each resulting in a premature invocation, hence before initializing my necessary service/repository stuff), I came up with the following solution:
Let spring create your shiro context without any automatic bean resolution to your services/repositories.
Let spring create your service/repository context, including mongodb
Create a simple class which will take care of your shiro-service coupling and configure it accordingly in your spring config. This class will be invoked after your shiro and service context has been successful set up.
To (1), sth. like this:
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="filterChainDefinitions">
<value>
<!-- Your definitions -->
</value>
</property>
</bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"
p:realm-ref="myShiroRealm" />
<bean id="myShiroRealm" class="com.acme.MyShiroRealm"
<!--no bean refs here-->
/>
To (2), sth. like this:
<bean id="myService" class="com.acme.MyService"
c:myRepository-ref="myRepository" />
...
<!-- Ask Spring Data to scan our repositories -->
<mongo:repositories base-package="com.acme.repository.impl.mongodb" />
To (3):
public class ShiroRealmServiceBridge {
public static void postInject( MyShiroServerRealm realm, MyService service ) {
realm.setService( service );
}
}
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass"><value>com.acme.ShiroRealmServiceBridge</value></property>
<property name="targetMethod"><value>postInject</value></property>
<property name="arguments">
<list>
<ref bean="myShiroRealm" />
<ref bean="myService" />
</list>
</property>
Advantages:
It works xD
No additional burden/dependencies on your shiro stuff
Complete spring configuration and setup, resulting in a consistent state after initialization
Disadvantage:
One time overhead setup
May result in an inconsistent state, which will complain at runtime rather than at startup, if you forget or bump the glue-configuration
The ShiroFilterFactoryBean implements the BeanPostProcessor and, since it has dependencies on the security manager w/ its own dependencies on data stores, data access objects, etc. it can cause a whole slew of Bean X of type Y is not eligible for getting processed by all BeanPostProcessors messages.
The worst part is that it seems to be just a way to see the Filter implementations that Spring is instantiating in order to track and possibly inject properties into AuthorizationFilters.
Frankly I don't need that headache just for filter tracking, so I created a custom version that did not include the BeanPostProcessor. I'm now forced to manually wire in Filter implementations to the beans "filters" property, but at least I don't have to deal with that error and the questionable status of my security manager and related beans.