Issue Details (XML | Word | Printable)

Key: SJC-113
Type: Bug Bug
Status: Resolved Resolved
Resolution: Fixed
Priority: Major Major
Assignee: Chris Beams
Reporter: Jens Fischer
Votes: 1
Watchers: 4
Operations

If you were logged in you would be able to see more operations.
Spring JavaConfig

No bean named '_exceptionTranslationFilter' is defined

Created: 20/May/08 03:43 PM   Updated: 12/Jun/08 10:16 AM   Resolved: 30/May/08 04:32 AM
Component/s: Internals, Public API
Affects Version/s: 1.0.0.M3
Fix Version/s: 1.0.0.M4

Time Tracking:
Original Estimate: Not Specified
Remaining Estimate: 0d
Remaining Estimate - 0d
Time Spent: 1d
Time Spent - 1d

File Attachments: 1. File exceptionTranslationFilter.tgz (3 kB)
2. Zip Archive mylyn-context.zip (17 kB)

Environment: Mac OS X 10.5, Maven 2.0.9, Spring 2.5.4, Spring JavaConfig 1.0.0.m3
Issue Links:
Depends
 
Related
 


 Description  « Hide
See http://forum.springframework.org/showthread.php?p=181230

Spring JavaConfig in conjunction with Spring Security prevents Appplication Context to start.

ERROR - TestContextManager.prepareTestInstance(258): Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@af5350] to prepare test instance [spring.security.bug.ExceptionTranslationFilterTest@86d315]
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:203)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:255)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:93)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.invokeTestMethod(SpringJUnit4ClassRunner.java:130)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:62)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:127)
at org.apache.maven.surefire.Surefire.run(Surefire.java:177)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:338)
at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:997)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named '_exceptionTranslationFilter' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:387)
at org.springframework.security.config.HttpSecurityConfigPostProcessor.injectAuthenticationEntryPointIntoExceptionTranslationFilter(HttpSecurityConfigPostProcessor.java:128)
at org.springframework.security.config.HttpSecurityConfigPostProcessor.postProcessBeanFactory(HttpSecurityConfigPostProcessor.java:38)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:501)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:363)
at org.springframework.config.java.process.ConfigurationProcessor$2.onApplicationEvent(ConfigurationProcessor.java:176)
at org.springframework.context.event.SimpleApplicationEventMulticaster$1.run(SimpleApplicationEventMulticaster.java:78)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:49)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:76)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:275)
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:737)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:384)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:96)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:44)
at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:173)
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:199)
... 20 more


Jens Fischer added a comment - 20/May/08 03:44 PM
Maven project containing JUnit test case to reproduce the bug

Luke Taylor added a comment - 21/May/08 03:33 PM - edited
JavaConfig is still pre-release and as such I can't see that this is a critical bug in Spring Security.

Luke Taylor added a comment - 22/May/08 10:58 AM
This issue appears to be related to the use of JavaConfig. If someone can produce a test case which is independent of JavaConfig I'll take a look at it. Otherwise we'll move this issue to that project.

Josh added a comment - 25/May/08 10:40 PM
I'm also experiencing this issue using Grails v1.0.2
If I use the same exact config with plan Spring MVC I don't receive this error.
It appears to me ( I may be wrong) that it has to do something with refreshing the spring context...

my securityContext.xml (where myApplicationContext.xml defines our services,daos, and spring security config)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:sec="http://www.springframework.org/schema/security"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:util="http://www.springframework.org/schema/util"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        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
                        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
                        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd
                http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.1.xsd">

  
       <import resource="classpath:myApplicationContext.xml" />

      
      
        <sec:http auto-config="true">
             <sec:intercept-url pattern="/**" access="ROLE_SUPERVISOR"/>
        </sec:http>
       
    <sec:authentication-provider user-service-ref="userDetailsDao"/>


</beans>


Grails refreshes the spring context which is why I'm thinking it has something to do with the refresh...
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:363)
    at org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext.refresh(GrailsWebApplicationContext.java:141)


The full stacktrace...
[34764] StackTrace Sanitizing stacktrace:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named '_exceptionTranslationFilter' is defined
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:387)
    at org.springframework.security.config.HttpSecurityConfigPostProcessor.injectAuthenticationEntryPointIntoExceptionTranslationFilter(HttpSecurityConfigPostProcessor.java:128)

    at org.springframework.security.config.HttpSecurityConfigPostProcessor.postProcessBeanFactory(HttpSecurityConfigPostProcessor.java:38)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:501)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:363)
    at org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext.refresh(GrailsWebApplicationContext.java:141)
    at org.codehaus.groovy.grails.commons.spring.DefaultRuntimeSpringConfiguration.getApplicationContext(DefaultRuntimeSpringConfiguration.java:130)
    at org.codehaus.groovy.grails.commons.spring.GrailsRuntimeConfigurator.configure(GrailsRuntimeConfigurator.java:277)
    at org.codehaus.groovy.grails.commons.spring.GrailsRuntimeConfigurator.configure(GrailsRuntimeConfigurator.java:242)
    at org.codehaus.groovy.grails.web.context.GrailsConfigUtils.configureWebApplicationContext(GrailsConfigUtils.java:107)
    at org.codehaus.groovy.grails.web.context.GrailsContextLoader.createWebApplicationContext(GrailsContextLoader.java:50)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45)
    at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:530)
    at org.mortbay.jetty.servlet.Context.startContext(Context.java:135)
    at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1218)
    at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:500)
    at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:448)
    at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
    at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:117)
    at org.mortbay.jetty.Server.doStart(Server.java:220)
    at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:226)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:899)
    at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:946)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:740)
    at org.codehaus.groovy.runtime.InvokerHelper.invokePojoMethod(InvokerHelper.java:765)
    at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:753)
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodN(ScriptBytecodeAdapter.java:167)
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethod0(ScriptBytecodeAdapter.java:195)
    at RunApp_groovy$_run_closure2_closure7.doCall(RunApp_groovy:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)

Chris Beams added a comment - 27/May/08 09:44 PM
I've verified that this is a JavaConfig issue. As Spring Security is not at fault here, we'll move this issue to the SJC project shortly.

Konstantyn Smirnov added a comment - 28/May/08 01:03 PM
My set-up:

Grails 1.0.2, SpringSecurity 2.0 (isolated from Grails), SJC is NOT used (at least explicitly)

Here's my ctx:

<?xml version="1.0" encoding="UTF-8"?>
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
       xmlns="http://www.springframework.org/schema/security"
       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-2.0.xsd
       http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">

  <http access-denied-page="/accessDenied.gsp">
    <intercept-url pattern="/abstractpoi/delete/**" access="ROLE_USER, ROLE_ADMIN" />
    <intercept-url pattern="/abstractpoi/createpoi/**" access="ROLE_USER, ROLE_ADMIN" />
    <intercept-url pattern="/abstractpoi/edit/*" access="ROLE_USER, ROLE_ADMIN" />
    <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <anonymous />

    <form-login authentication-failure-url="/login/login.gsp"
                default-target-url="/login/abstractPOI/showCategories"
                login-page="/login/login.gsp" />

    <logout logout-success-url="/login/login.gsp" />
    <remember-me />
  </http>

  <authentication-provider user-service-ref="userDetailsService">
    <password-encoder hash="sha">
      <salt-source user-property="id"/>
    </password-encoder>
  </authentication-provider>
  
  <b:bean id="userDetailsService" class="com.wextent.acegi.dao.UserAccountDao"/>

</b:beans>

I tried similar context on another project, but result is the same:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named '_exceptionTranslationFilter' is defined


Chris Beams added a comment - 28/May/08 01:34 PM
Konstantyn,

It would be very helpful if you would put together and attach a very simple project that demonstrates the error you're getting. If I can reproduce it locally I'll have a much better chance of tracking it down.

Thanks!

Chris Beams added a comment - 30/May/08 04:32 AM
Resolved as of revision 576 - moldarion's originally submitted 'exceptionTranslationFilter' test case now passes.

Cause:

JavaConfig was being too eager about copying BeanFactoryPostProcessors from the parent bean factory into its 'internal' or 'hidden' bean factory. This copying must now be explicitly configured:

Via XML:

    <bean class="org.springframework.config.java.process.ConfigurationPostProcessor">
    <bean class="com.acme.MyConfig">

    <!-- this BFPP will be copied into the hidden bean factory and will post-process all hidden bean definitions -->
    <bean id="myBFPP" class="com.acme.MyBeanFactoryPostProcessor">
        <meta key="COPY_HIDDEN" value="true"/>
    </bean>
    
    <!-- this BFPP will not be copied, and will apply only to 'public' beans -->
    <bean id="otherBFPP" class="com.acme.OtherBeanFactoryPostProcessor"/>


Via Java:

    @Configuration
    public class MyConfig {
        @Bean
        public Foo publicBean() { ... }
        
        @Bean
        Bar hiddenBean() { ... }
        
        // this BFPP will be applied to both the beans above
        @Bean(meta=@Meta(key=BeanMetadata.COPY_HIDDEN, value="true"))
        public BeanFactoryPostProcessor myBPP() {
            return new com.acme.MyBeanFactoryPostProcessor();
        }

        // this BFPP will be applied only to publicBean() above
        @Bean
        public BeanFactoryPostProcessor otherBPP() {
            return new com.acme.OtherBeanFactoryPostProcessor();
        }
                
    }

See also SJC-22, SJC-47

Taras Tielkes added a comment - 30/May/08 06:19 AM
Sure looks like an ugly exposure of internal details ;-)

Chris Beams added a comment - 30/May/08 11:35 AM - edited
Hi Taras,

I couldn't agree more, actually. Unfortunately, this was a lesser-of-two-evils kind of choice:

a) continue blindly copying BFPPs to the hidden bean factory and risk violating assumptions that it's reasonable for BFPPs to make
b) put the burden on SJC users to be explicit about propagating BFPPs

I think that (b) is the better of the two choices, although I don't like either.

My reasons for this:

* SJC users know which beans are hidden and so can make an informed decision about whether or not to apply BFPPs to them.
* most importantly, I think the use cases for applying BFPPs in an SJC context are quite small. Given the fact that SJC @Bean declarations don't have any notion of PropertyValues, there's little for BFPPs to do. There are some notable exceptions here, I'm sure, but I think it'll be the 5% case that a user both needs a @Bean to be hidden and actually can make use of a BFPP.
* option (a) isn't really an option at all. It breaks Spring Security, as this bug pointed out. The onus was on SJC to do something to rectify this.

Between BeanFactoryPostProcessing and BeanPostProcessing, I think BeanPostProcessing is the more important of the two, and the good news is that it looks like it's pretty well worked out now with no significant downsides to its implementation.

I'm wide open to suggestions here, especially if you have ideas around how to make enabling this functionality better from a user experience point of view.

Thanks for your feedback. I know you've been around and watching a number of SJC issues for a long while, so your thoughts are especially appreciated!