I'm having a problem with RESTlet Framework configuration with Spring. I want to have one global filter for all requests and responses. I guess I can use Filter class and it's methods beforeHandle, afterHandle and setNext like this:
Filter.beforeHandle() -> Router -> Filter.afterHandle()
The problem is, that I'm using Spring configured RESTlet and I don't know if the regular Filter will work correctly with SpringRouter from org.restlet.ext.spring package. My current restlet configuration is as follows:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="root" class="org.restlet.ext.spring.SpringRouter">
<property name="attachments">
<map>
<entry key="/login">
<bean class="org.restlet.ext.spring.SpringFinder">
<lookup-method name="create"
bean="loginResource" />
</bean>
</entry>
</map>
</property>
</bean>
</beans>
I'm thinking about adding a bean with id root and class that extends class Filter, and pass to it as property next a bean with id router (which currently is called root). What do you think about this solution?
Mixing Restlet classes from the Spring extension with other one shouldn't be an issue. Spring* classes only provide additional configurability.
We've been seeing inconsistent NoSuchBeanDefinitionException since upgrading from Spring 3.0 to Spring 3.1. It happens to only about 2% of our hosts and even then the problem is not consistent in a single host since it might not happen after restarting the same server.
Here's the error :
nested exception is org.springframework.beans.factory.BeanCreationException: Could
not autowire field: private com.google.common.util.concurrent.ListeningExecutorService
com.amazon.ms3.container.impl.ExecutionEnvironmentImpl.functionThreadPool;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No matching bean of type [com.google.common.util.concurrent.ListeningExecutorService]
found for dependency: expected at least 1 bean which qualifies as
autowire candidate for this dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true),
#org.springframework.beans.factory.annotation.Qualifier(value=functionThreadPool)}
| at org.springframework.beans.factory.annotation
.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues...
Here's the bean code (irrelevant code removed):
public class ExecutionEnvironmentImpl extends ExecutionEnvironment {
#Autowired
#Qualifier("functionThreadPool")
private ListeningExecutorService functionThreadPool;
public ExecutionEnvironmentImpl() {
}
public void setFunctionThreadPool(ListeningExecutorService functionThreadPool) {
this.functionThreadPool = functionThreadPool;
}
}
And here's the configuration file (irrelevant configuration removed):
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
">
<bean id="executionEnvironment" class="com.amazon.ms3.container.impl.ExecutionEnvironmentImpl" scope="prototype"/>
<!-- ThreadPool for executing tenant functions asynchronously -->
<bean id="functionThreadPool" class="com.google.common.util.concurrent.MoreExecutors" factory-method="listeningDecorator">
<constructor-arg>
<bean class="java.util.concurrent.Executors" factory-method="newCachedThreadPool"/>
</constructor-arg>
</bean>
</beans>
The Qualifier annotation isn't much of use anymore since we don't have other ListeningExecutorService defined but I don't believe it should be causing any problem.
Any ideas of what might be causing this? I've been thinking about removing the autowiring completely but I'd like to understand why this is happening in the first place.
Thanks!
This is possibly some timing-related issue in the order that Spring brings up beans in the application context. It may be worth explicitly telling Spring to create the functionThreadPool first to ensure that it is available for autowiring into the executionEnvironment. To do that, you can use the depends-on attribute:
<bean id="executionEnvironment"
class="com.amazon.ms3.container.impl.ExecutionEnvironmentImpl"
scope="prototype"
depends-on="functionThreadPool"/>
<!-- ThreadPool for executing tenant functions asynchronously -->
<bean id="functionThreadPool" class="com.google.common.util.concurrent.MoreExecutors" factory-method="listeningDecorator">
<constructor-arg>
<bean class="java.util.concurrent.Executors" factory-method="newCachedThreadPool"/>
</constructor-arg>
</bean>
</beans>
If you intend to use autowiring then you should have the <context:annotation-config> element in the configuration also - so that Spring knows to autowire the functionThreadPool into the executionEnvironment.
After trying depends-on and even wiring the bean directly like shown below :
<bean id="executionEnvironment" class="com.amazon.ms3.container.impl.ExecutionEnvironmentImpl" scope="prototype">
<property name="functionThreadPool" ref="functionThreadPool"/>
</bean>
<!-- ThreadPool for executing tenant functions asynchronously -->
<bean id="functionThreadPool" class="com.google.common.util.concurrent.MoreExecutors" factory-method="listeningDecorator">
<constructor-arg>
<bean class="java.util.concurrent.Executors" factory-method="newCachedThreadPool"/>
</constructor-arg>
</bean>
we were still seeing the same error on some occasions. The only thing that fixed it was to remove the #Autowired annotation in the ExecutionEnvironmentImpl class.
We didn't really fix the problem but more like avoiding it. I wish I could provide a better answer.
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.
ok, enough. I couldn't make this work. I am a newbie to Spring transactions and using the #Transactional annotation in my service to manage transactions. Below is my spring bean configuration file.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/myapp"/>
<!-- other <bean/> definitions here -->
</beans>
and I annotate my service:
#Transactional
public class MyServiceImpl implements MyService {
...
}
I notice two things
The connection that I get in my DAO [using DataSourceUtils.getConnection(dsName)] has the autocommit enabled [true].
As far as I debugged there doesn't look to be any transaction that has begun during my service method invocation.
Anyone had this problem?
I use Hibernate with the HibernateTransactionManager myself, so I'm not too familiar with how the JDBC transaction manager works. Have you inspected the callstack to see whether or not TransactionInterceptor is in there ? If it is, then the transactional annotation is working, and you may just be missing something else. If you haven't looked for it, what makes you think that it's not working ? To eliminate the obvious, have you explicitly set a setting in your JDBC configuration to disable autocommit ?
I have an existing Spring MVC apps written in 2.5.
I wanted to use the new annotation controller. I somewhat see that it is really flexible and would answer my other needs.
My problem is, it seems I cannot mix them both.
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan
base-package="com.test.web" />
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<!-- Controller Mappings Here -->
<bean id="homeController" class="com.test.web.HomeController">
<property name="cacheSeconds" value="120" />
</bean>
//other plain old spring mvc controller
When I ran my app and hit the home page, I get below error:
javax.servlet.ServletException: No adapter for handler [com.test.web.HomeController#cca07b]: Does your handler implement a supported interface like Controller?
I am not sure but I think something is conflicting. This is a fairly large Spring MVC apps and I don't want to change those modules that were working already using the old Spring Base Controller.
My goal is to only use the annotation controller on my new enhancement.
You don't need to declare DefaultAnnotationHandlerMapping and AnnotationMethodHandlerAdapter. The context has these registered by default, along with adapters for old-style controllers.
When you declare them explicitly like this, the default ones are removed, and the context will only support the ones you declare.