Skip to content

UnsupportedOperationException for request scoped bean with parameter #362

Description

@TobiasBerndt

Versions:

  • Spring boot 2.7.6
  • Joinfaces 4.7.4
  • Rewrite 3.5.1.Final
  • JSF 2.3

On initializing RewriteFilter for request scoped bean 'MyController' (see below) during spring boot application start-up the following exception occurs.

Exception starting filter [OCPsoft Rewrite Filter]

java.lang.UnsupportedOperationException: null
	at java.base/java.util.AbstractMap.put(AbstractMap.java:209)
	at org.springframework.web.context.request.FacesRequestAttributes.setAttribute(FacesRequestAttributes.java:112)
	at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:46)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:371)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:673)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:661)
	at org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:1300)
	at org.joinfaces.autoconfigure.rewrite.SpringBootBeanNameResolver.resolveBeanNames(SpringBootBeanNameResolver.java:80)
	at org.joinfaces.autoconfigure.rewrite.SpringBootBeanNameResolver.getBeanName(SpringBootBeanNameResolver.java:49)
	at org.ocpsoft.rewrite.el.TypeBasedExpression.lookupBeanName(TypeBasedExpression.java:72)
	at org.ocpsoft.rewrite.el.TypeBasedExpression.getExpression(TypeBasedExpression.java:55)
	at org.ocpsoft.rewrite.el.TypeBasedExpression.toString(TypeBasedExpression.java:108)
	at java.base/java.lang.String.valueOf(String.java:2951)
	at java.base/java.lang.StringBuilder.append(StringBuilder.java:168)
	at org.ocpsoft.rewrite.el.El$ElProperty.toString(El.java:335)
	at org.ocpsoft.rewrite.param.ParameterBuilder.addOrReplaceBinding(ParameterBuilder.java:83)
	at org.ocpsoft.rewrite.param.ParameterBuilder.bindsTo(ParameterBuilder.java:69)
	at org.ocpsoft.rewrite.param.ParameterBuilder.bindsTo(ParameterBuilder.java:29)
	at org.ocpsoft.rewrite.config.ConfigurationLoader$1.call(ConfigurationLoader.java:196)
	at org.ocpsoft.rewrite.config.ParameterizedConditionVisitor.visit(ParameterizedConditionVisitor.java:40)
	at org.ocpsoft.rewrite.config.ParameterizedConditionVisitor.visit(ParameterizedConditionVisitor.java:27)
	at org.ocpsoft.rewrite.config.ConditionVisit.visit(ConditionVisit.java:53)
	at org.ocpsoft.rewrite.config.ConditionVisit.accept(ConditionVisit.java:44)
	at org.ocpsoft.rewrite.config.ConfigurationLoader.build(ConfigurationLoader.java:204)
	at org.ocpsoft.rewrite.config.ConfigurationLoader.buildCached(ConfigurationLoader.java:118)
	at org.ocpsoft.rewrite.config.ConfigurationLoader.loadConfiguration(ConfigurationLoader.java:81)
	at org.ocpsoft.rewrite.servlet.impl.DefaultHttpRewriteProvider.init(DefaultHttpRewriteProvider.java:81)
	at org.ocpsoft.rewrite.servlet.impl.DefaultHttpRewriteProvider.init(DefaultHttpRewriteProvider.java:55)
	at org.ocpsoft.rewrite.servlet.RewriteFilter.init(RewriteFilter.java:142)
	at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:272)
	at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:106)
	at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4609)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5248)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1393)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1383)
	at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java)
	at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
	at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140)
	at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:916)
	at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:835)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1393)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1383)
	at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java)
	at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
	at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140)
	at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:916)
	at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:265)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
	at org.apache.catalina.core.StandardService.startInternal(StandardService.java:430)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
	at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:930)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
	at org.apache.catalina.startup.Tomcat.start(Tomcat.java:486)
	at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:123)
	at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.<init>(TomcatWebServer.java:104)
	at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:479)
	at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:211)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:184)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:162)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:577)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292)
@Join(path = "/mypath", to = "/pages/myPage.jsf")
public class MyController {
   @Parameter("someParam")
   @Setter
   @Getter
   private String someParam;
}
@Bean
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public MyController myController() {
   return new MyController();
}

Activity

  1. lincolnthree commented on Feb 28, 2023

    @lincolnthree
    Member

    @TobiasBerndt Apologies for the delay. The holidays were difficult.

    If you are still struggling with this, could you please provide a sample project with minimal dependencies, so I can try to reproduce the issue?

  2. TobiasBerndt commented on Mar 2, 2023

    @TobiasBerndt
    Author

    @lincolnthree
    I have created this sample project https://github.com/TobiasBerndt/rewrite-example
    First I have to mention that I had another issue in the past in rewrite version 3.4.3.Final.
    So I forked rewrite and modified the SpringBeanNameResolver (rewrite-integration-spring) class to not throw below exception.
    This exception occurred also on startup and is related @Parameter.
    With the forked version I now get the exception of my first post.
    Did I use @Parameter in a wrong way?

    java.lang.IllegalStateException: Unable to get current WebApplicationContext
    	at org.ocpsoft.rewrite.spring.SpringBeanNameResolver.getBeanName(SpringBeanNameResolver.java:45) ~[rewrite-integration-spring-3.5.1.Final.jar:3.5.1.Final]
    	at org.ocpsoft.rewrite.el.TypeBasedExpression.lookupBeanName(TypeBasedExpression.java:72) ~[rewrite-servlet-3.5.1.Final.jar:3.5.1.Final]
    	at org.ocpsoft.rewrite.el.TypeBasedExpression.getExpression(TypeBasedExpression.java:55) ~[rewrite-servlet-3.5.1.Final.jar:3.5.1.Final]
    	at org.ocpsoft.rewrite.el.TypeBasedExpression.toString(TypeBasedExpression.java:108) ~[rewrite-servlet-3.5.1.Final.jar:3.5.1.Final]
    	at java.base/java.lang.String.valueOf(String.java:2951) ~[na:na]
    	at java.base/java.lang.StringBuilder.append(StringBuilder.java:168) ~[na:na]
    	at org.ocpsoft.rewrite.el.El$ElProperty.toString(El.java:335) ~[rewrite-servlet-3.5.1.Final.jar:3.5.1.Final]
    	at org.ocpsoft.rewrite.param.ParameterBuilder.addOrReplaceBinding(ParameterBuilder.java:83) ~[rewrite-servlet-3.5.1.Final.jar:3.5.1.Final]
    	at org.ocpsoft.rewrite.param.ParameterBuilder.bindsTo(ParameterBuilder.java:69) ~[rewrite-servlet-3.5.1.Final.jar:3.5.1.Final]
    	at org.ocpsoft.rewrite.param.ParameterBuilder.bindsTo(ParameterBuilder.java:29) ~[rewrite-servlet-3.5.1.Final.jar:3.5.1.Final]
    	at org.ocpsoft.rewrite.config.ConfigurationLoader$1.call(ConfigurationLoader.java:196) ~[rewrite-servlet-3.5.1.Final.jar:3.5.1.Final]
    	at org.ocpsoft.rewrite.config.ParameterizedConditionVisitor.visit(ParameterizedConditionVisitor.java:40) ~[rewrite-servlet-3.5.1.Final.jar:3.5.1.Final]
    	at org.ocpsoft.rewrite.config.ParameterizedConditionVisitor.visit(ParameterizedConditionVisitor.java:27) ~[rewrite-servlet-3.5.1.Final.jar:3.5.1.Final]
    	at org.ocpsoft.rewrite.config.ConditionVisit.visit(ConditionVisit.java:53) ~[rewrite-servlet-3.5.1.Final.jar:3.5.1.Final]
    	at org.ocpsoft.rewrite.config.ConditionVisit.accept(ConditionVisit.java:44) ~[rewrite-servlet-3.5.1.Final.jar:3.5.1.Final]
    	at org.ocpsoft.rewrite.config.ConfigurationLoader.build(ConfigurationLoader.java:204) ~[rewrite-servlet-3.5.1.Final.jar:3.5.1.Final]
    	at org.ocpsoft.rewrite.config.ConfigurationLoader.buildCached(ConfigurationLoader.java:118) ~[rewrite-servlet-3.5.1.Final.jar:3.5.1.Final]
    	at org.ocpsoft.rewrite.config.ConfigurationLoader.loadConfiguration(ConfigurationLoader.java:81) ~[rewrite-servlet-3.5.1.Final.jar:3.5.1.Final]
    	at org.ocpsoft.rewrite.servlet.impl.DefaultHttpRewriteProvider.init(DefaultHttpRewriteProvider.java:81) ~[rewrite-servlet-3.5.1.Final.jar:3.5.1.Final]
    	at org.ocpsoft.rewrite.servlet.impl.DefaultHttpRewriteProvider.init(DefaultHttpRewriteProvider.java:55) ~[rewrite-servlet-3.5.1.Final.jar:3.5.1.Final]
    	at org.ocpsoft.rewrite.servlet.RewriteFilter.init(RewriteFilter.java:142) ~[rewrite-servlet-3.5.1.Final.jar:3.5.1.Final]
    	at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:272) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:106) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4609) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5248) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1393) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1383) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264) ~[na:na]
    	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java) ~[na:na]
    	at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140) ~[na:na]
    	at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:916) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:835) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1393) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1383) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264) ~[na:na]
    	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java) ~[na:na]
    	at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140) ~[na:na]
    	at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:916) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:265) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at org.apache.catalina.core.StandardService.startInternal(StandardService.java:430) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:930) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at org.apache.catalina.startup.Tomcat.start(Tomcat.java:486) ~[tomcat-embed-core-9.0.69.jar:9.0.69]
    	at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:123) ~[spring-boot-2.7.6.jar:2.7.6]
    	at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.<init>(TomcatWebServer.java:104) ~[spring-boot-2.7.6.jar:2.7.6]
    	at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:479) ~[spring-boot-2.7.6.jar:2.7.6]
    	at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:211) ~[spring-boot-2.7.6.jar:2.7.6]
    	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:184) ~[spring-boot-2.7.6.jar:2.7.6]
    	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:162) ~[spring-boot-2.7.6.jar:2.7.6]
    	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:577) ~[spring-context-5.3.24.jar:5.3.24]
    	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.6.jar:2.7.6]
    	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731) ~[spring-boot-2.7.6.jar:2.7.6]
    	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.6.jar:2.7.6]
    	at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) ~[spring-boot-2.7.6.jar:2.7.6]
    	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) ~[spring-boot-2.7.6.jar:2.7.6]
    	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) ~[spring-boot-2.7.6.jar:2.7.6]
    	at com.example.rewrite.RewriteApplication.main(RewriteApplication.java:10) ~[classes/:na]
    
  3. lincolnthree commented on Mar 6, 2023

    @lincolnthree
    Member

    Ok, that makes some sense. If the WebApplicationContext is yet not available in a request (for instance, if Spring hasn't started yet), it's possible that the ServletFilter ordering needs to be adjusted so that Spring initializes first, then Rewrite does.

    You could try re-ordering the servlet filters in your application - let me know if that resolves the exception?

    I've got this issue on my tasks list for next day or so, today if I can finish up the Monday tasks. I'll take a closer look soon. Sorry for the delay.

  4. TobiasBerndt commented on Mar 14, 2023

    @TobiasBerndt
    Author

    I saw in org.joinfaces.autoconfigure.rewrite.RewriteFilterProperties and org.joinfaces.autoconfigure.rewrite.RewriteAutoConfiguration that RewriteFilter has lowest precedence by default.
    Is there anything I should configure differently?
    The issue only occurs with @Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS). For e.g. singleton bean there is no issue.

  5. lincolnthree commented on Mar 16, 2023

    @lincolnthree
    Member

    Hi Tobias, apologies for the delay. I've got some crazy stuff happening here right now. I still need to dig more, but...

    I'm looking at your first (original) exception where @Parameter is throwing java.lang.UnsupportedOperationException: null

    On first glance I do see one issue, but I'm not sure if it would cause this problem. First, you have @Parameter("someParam"), but your @Join path does not accept this parameter. See the docs here: https://github.com/ocpsoft/rewrite/blob/6.0.0.Alpha1/config-annotations/src/main/java/org/ocpsoft/rewrite/annotation/Parameter.java

    You should have something like this instead:

    @Join(path = "/mypath/{someParam}", to = "/index.jsf")
    

    Otherwise you are specifying a parameter which is unbound. I'm honestly not sure we even have a test for this scenario so it's definitely something I'm going to take a closer look at.

  6. lincolnthree commented on Mar 16, 2023

    @lincolnthree
    Member

    As for the startup error. I'm worried that this might be some circular initialization loop where SpringBoot is trying to start the WebApplicationContext, then Rewrite tries to start up and request bean names to create the configuration, then SpringBoot says, "Hey, I'm not ready yet and don't have a WebApplicationContext", and returns null back to Rewrite.

    Digging deeper.

  7. TobiasBerndt commented on Mar 17, 2023

    @TobiasBerndt
    Author

    First of all thank you for taking care about this issue.

    Hi Tobias, apologies for the delay. I've got some crazy stuff happening here right now. I still need to dig more, but...

    I'm looking at your first (original) exception where @Parameter is throwing java.lang.UnsupportedOperationException: null

    On first glance I do see one issue, but I'm not sure if it would cause this problem. First, you have @Parameter("someParam"), but your @Join path does not accept this parameter. See the docs here: https://github.com/ocpsoft/rewrite/blob/6.0.0.Alpha1/config-annotations/src/main/java/org/ocpsoft/rewrite/annotation/Parameter.java

    You should have something like this instead:

    @Join(path = "/mypath/{someParam}", to = "/index.jsf")
    

    Otherwise you are specifying a parameter which is unbound. I'm honestly not sure we even have a test for this scenario so it's definitely something I'm going to take a closer look at.

    I use the parameter as a GET parameter e.g. http://localhost:8080/mypath?someParam=something and I thought the only difference to having it not in the path is that it's not mandatory to set. At least in the example here the parameter is also not part of join path.

    As for the startup error. I'm worried that this might be some circular initialization loop where SpringBoot is trying to start the WebApplicationContext, then Rewrite tries to start up and request bean names to create the configuration, then SpringBoot says, "Hey, I'm not ready yet and don't have a WebApplicationContext", and returns null back to Rewrite.

    Digging deeper.

    To understand wants going on there I have set a breakpoint in org.ocpsoft.rewrite.el.TypeBasedExpression.lookupBeanName() and the iterator for BeanNameResolver has 4 entries. It looks like they behave differently (returning null or throwing exception). If a BeanNameResolver returns null the next BeanNameResolver is taken but the order of BeanNameResolver calls seems to be random.

    • org.ocpsoft.rewrite.el.DefaultBeanNameResolver --> returns null for singleton and request scoped bean
    • org.ocpsoft.rewrite.faces.FacesBeanNameResolver --> returns null for singleton and request scoped bean
    • org.ocpsoft.rewrite.spring.SpringBeanNameResolver --> for singleton and request scoped bean is results in java.lang.IllegalStateException: Unable to get current WebApplicationContext
    • org.joinfaces.autoconfigure.rewrite.SpringBootBeanNameResolver
      • for singleton scoped bean --> bean gets resolved
      • for request scoped bean --> java.lang.UnsupportedOperationException
  8. lincolnthree commented on Mar 20, 2023

    @lincolnthree
    Member

    Okay, so I think I know why this is happening. First, the startup error is caused because you need to extend SpringBootServletInitializer in your RewriteConfiguration to tell Spring Boot that this Configuration uses the WebApplicationContext (which changes initialization order.)

    This resolves the startup error:

    @Configuration
    public class RewriteConfiguration extends SpringBootServletInitializer
    {
    	@Bean
    	@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
    	public MyController myController()
    	{
    		return new MyController();
    	}
    }
    

    Next, regarding the PrettyFaces error when loading the Parameter config, I am still working on that. But it's being caused because the request-scoped bean is being looked up during application startup for some reason. It shouldn't be. The EL container should be able to return metadata about the bean without instantiating the bean. I'm still researching.

  9. TobiasBerndt commented on Mar 21, 2023

    @TobiasBerndt
    Author

    I thought SpringBootServletInitializer is only needed if you want to run the application as WAR.
    My sample application is running as JAR with an embedded tomcat.
    Javadoc of SpringBootServletInitializer:

    An opinionated WebApplicationInitializer to run a SpringApplication from a traditional WAR deployment.
    [...]
    Note that a WebApplicationInitializer is only needed if you are building a war file and deploying it. If you prefer to run an embedded web server then you won't need this at all.

    Nevertheless I tried it with SpringBootServletInitializer but exceptions during startup are still thrown.

  10. lincolnthree commented on Mar 21, 2023

    @lincolnthree
    Member

    Nevertheless I tried it with SpringBootServletInitializer but exceptions during startup are still thrown.

    [Edit. You are correct -- This doesn't fix the issue. I think it just changed the order of classloading and a different issue came up first.] Please ignore.

  11. lincolnthree commented on Mar 21, 2023

    @lincolnthree
    Member

    Ok, so from what I can tell, it appears that Spring Boot is misconfigured or incompatible somehow. The Spring WebApplicationContext is not available during Servlet Filter startup, and it needs to be. I am not an expert in Spring Boot and its startup lifecycle, so I'm not sure how much I will be able to help, here. Know anyone with Spring Boot expertise?

    Generally, when configuring Spring Manually, you'd ensure this happens by ordering Spring's WebContextListener to run before Rewrite's.

    2023-03-21 11:46:58.515  WARN 47756 --- [           main] o.s.w.c.s.SpringBeanAutowiringSupport    : 
    Current WebApplicationContext is not available for processing of FacesRewriteLifecycleListener:
    Make sure this class gets constructed in a Spring web application after the Spring
    WebApplicationContext has been initialized. Proceeding without injection.
    

    I've tried all the solutions proposed here: https://stackoverflow.com/questions/33486219/spring-boot-no-webapplicationcontext-found, but I suspect something is interfering with or overriding the boot order. I might suggest checking with the JoinFaces folks and see what they are doing in this regard, and if there is any way to override their defined start order (if they've set one, which I presume they have.)

  12. larsgrefer commented on Mar 21, 2023

    @larsgrefer
    Contributor

    As for the startup error. I'm worried that this might be some circular initialization loop where SpringBoot is trying to start the WebApplicationContext, then Rewrite tries to start up and request bean names to create the configuration, then SpringBoot says, "Hey, I'm not ready yet and don't have a WebApplicationContext", and returns null back to Rewrite.

    Digging deeper.

    The "problem" is that org.ocpsoft.rewrite.spring.SpringServiceEnricher does not have access to the current ServletContext, so it can't access the ServletContext attribute org.springframework.web.context.WebApplicationContext.ROOT in which the WebApplicationContext could be found.

    See also org.springframework.web.context.support.WebApplicationContextUtils#getRequiredWebApplicationContext

    Instead it relies on org.springframework.web.context.ContextLoader#getCurrentWebApplicationContext which is null for Spring Boot Applications, because they aren't loaded by the ContextLoaders. (The only exception might be WAR-based Spring-Boot Application, deployed to an existing servlet container)

  13. lincolnthree commented on Mar 21, 2023

    @lincolnthree
    Member

    Hey @larsgrefer! Thanks for the info and for pointing me toward getRequiredWebApplicationContextg The issue here is that the JoinFaces BeanNameResolver is still using ApplicationContext.getBeansOfType. So it's going to fail when Rewrite attempts to configure Bean names and parameters (which is what's happening to @TobiasBerndt) and the Context isn't found.

    I think the better solution here would be to make the Rewrite SpringBeanNameResolver aware of the ServletContext so that it can properly attempt to access the WebApplicationContext in Spring Boot applications using the method you recommended. Then you'd be able to remove your JoinFaces SPI implementation. Or you can make yours implement ContextListener and fix it that way too.

    Here's what I propose, regardless of where the fix goes:

    /*
     * Copyright 2011 <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
     * 
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     * 
     *     http://www.apache.org/licenses/LICENSE-2.0
     * 
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    package org.ocpsoft.rewrite.spring;
    
    import java.util.HashSet;
    import java.util.Set;
    
    import org.ocpsoft.logging.Logger;
    import org.ocpsoft.rewrite.el.spi.BeanNameResolver;
    import org.springframework.beans.factory.ListableBeanFactory;
    import org.springframework.core.PriorityOrdered;
    import org.springframework.web.context.WebApplicationContext;
    
    /**
     * {@link BeanNameResolver} implementation for Spring.
     * 
     * @author Christian Kaltepoth
     * @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
     */
    public class SpringBeanNameResolver implements BeanNameResolver
    {
       private final Logger log = Logger.getLogger(SpringBeanNameResolver.class);
    
       @Override
       public String getBeanName(Class<?> clazz)
       {
          WebApplicationContext context = SpringWebApplicationContextProvider.getWebApplicationContext();
          if (context == null) {
             throw new IllegalStateException("Unable to get current WebApplicationContext");
          }
    
          // obtain a map of bean names
          Set<String> beanNames = resolveBeanNames(context, clazz);
    
          // no beans of that type, nothing we can do
          if (beanNames == null || beanNames.size() == 0) {
             return null;
          }
    
          // more than one result -> warn the user
          else if (beanNames.size() > 1) {
             log.warn("Spring knows more than one bean of type [{}]", clazz.getName());
             return null;
          }
    
          // exactly one result -> we got a name
          else {
             return beanNames.iterator().next();
          }
    
       }
    
       /**
        * Will ignore scoped proxy target bean names.
        * 
        * @see https://github.com/ocpsoft/rewrite/issues/170
        */
       private Set<String> resolveBeanNames(ListableBeanFactory beanFactory, Class<?> clazz)
       {
    
          final Set<String> result = new HashSet<String>();
    
          String[] names = beanFactory.getBeanNamesForType(clazz); <--- NOTE: This is the important change right here.
          if (names != null) {
             for (String name : names) {
                if (name != null && !name.startsWith("scopedTarget.")) {
                   result.add(name);
                }
             }
          }
    
          return result;
    
       }
    
    }
    
    

    I am working on a new release/snapshot that should resolve this, regardless :) Let's see if we can get it taken care of!

  14. lincolnthree commented on Mar 21, 2023

    @lincolnthree
    Member

    Proof it works :)

    image

  15. larsgrefer commented on Mar 21, 2023

    @larsgrefer
    Contributor

    The interesting SPI is ServiceEnricher once this works correctly, the other Spring SPI Implementations can get their ApplicationContext reference from the enriched by just implementing ApplicationContextAware

  16. lincolnthree commented on Mar 21, 2023

    @lincolnthree
    Member

    The interesting SPI is ServiceEnricher once this works correctly, the other Spring SPI Implementations can get their ApplicationContext reference from the enriched by just implementing ApplicationContextAware

    That might work if we switch to using processInjectionBasedOnServletContext. Let me see if I can make that happen.

  17. larsgrefer commented on Mar 21, 2023

    @larsgrefer
    Contributor

    processInjectionBasedOnServletContext also uses org.springframework.web.context.support.WebApplicationContextUtils#getRequiredWebApplicationContext internally.

  18. lincolnthree commented on Mar 21, 2023

    @lincolnthree
    Member

    processInjectionBasedOnServletContext also uses org.springframework.web.context.support.WebApplicationContextUtils#getRequiredWebApplicationContext internally.

    Right, that's why I think it should be used if possible. Once we have access to the ServletContext that would prevent the call to getCurrentWebApplicationContext. Or am I confused?

  19. lincolnthree commented on Mar 21, 2023

    @lincolnthree
    Member

    BAM. It works. This is MUCH cleaner. Thanks @larsgrefer.

    
      .   ____          _            __ _ _
     /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
    ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
     \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
      '  |____| .__|_| |_|_| |_\__, | / / / /
     =========|_|==============|___/=/_/_/_/
     :: Spring Boot ::                (v2.7.6)
    
    2023-03-21 16:20:14.422  INFO 63251 --- [           main] com.example.rewrite.RewriteApplication   : Starting RewriteApplication using Java 11.0.18 on mshark.local with PID 63251 (/Users/lincoln/projects/ocpsoft/rewrite-issue-362/target/classes started by lincoln in /Users/lincoln/projects/ocpsoft/rewrite-issue-362)
    2023-03-21 16:20:14.424  INFO 63251 --- [           main] com.example.rewrite.RewriteApplication   : No active profile set, falling back to 1 default profile: "default"
    2023-03-21 16:20:15.025  INFO 63251 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
    2023-03-21 16:20:15.033  INFO 63251 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
    2023-03-21 16:20:15.033  INFO 63251 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.69]
    2023-03-21 16:20:15.193  INFO 63251 --- [           main] org.apache.jasper.servlet.TldScanner     : At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
    2023-03-21 16:20:15.204  INFO 63251 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
    2023-03-21 16:20:15.204  INFO 63251 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 736 ms
    2023-03-21 16:20:15.220  WARN 63251 --- [           main] o.s.w.c.s.SpringBeanAutowiringSupport    : Current WebApplicationContext is not available for processing of SLF4JLogAdapterFactory: Make sure this class gets constructed in a Spring web application after the Spring WebApplicationContext has been initialized. Proceeding without injection.
    2023-03-21 16:20:15.733  INFO 63251 --- [           main] vletContainerInitializerRegistrationBean : Resolving classes for com.sun.faces.config.FacesInitializer took 0.485617667s
    2023-03-21 16:20:15.747  WARN 63251 --- [           main] o.s.w.c.s.SpringBeanAutowiringSupport    : Current WebApplicationContext is not available for processing of SpringServiceEnricher: Make sure this class gets constructed in a Spring web application after the Spring WebApplicationContext has been initialized. Proceeding without injection.
    2023-03-21 16:20:15.775  INFO 63251 --- [           main] j.e.resource.webcontainer.jsf.config     : Initializing Mojarra 2.3.5 ( 20180516-1910 bf35b0f6c540c69e80e6da962a2b62756838ac41) for context ''
    2023-03-21 16:20:15.843  INFO 63251 --- [           main] j.e.r.webcontainer.jsf.application       : JSF1048: PostConstruct/PreDestroy annotations present.  ManagedBeans methods marked with these annotations will have said annotations processed.
    2023-03-21 16:20:15.906  INFO 63251 --- [           main] o.o.rewrite.faces.RewritePhaseListener   : RewritePhaseListener starting up.
    2023-03-21 16:20:16.011  INFO 63251 --- [           main] o.ocpsoft.rewrite.servlet.RewriteFilter  : RewriteFilter starting up...
    2023-03-21 16:20:16.023  INFO 63251 --- [           main] o.ocpsoft.rewrite.servlet.RewriteFilter  : Loaded [3] org.ocpsoft.rewrite.servlet.spi.RewriteLifecycleListener [org.ocpsoft.rewrite.faces.FacesRewriteLifecycleListener<0>, org.ocpsoft.rewrite.servlet.impl.DefaultRewriteLifecycleListener<2147483647>, org.ocpsoft.rewrite.servlet.config.lifecycle.JoinRewriteLifecycleListener<2147483647>]
    2023-03-21 16:20:16.023  INFO 63251 --- [           main] o.ocpsoft.rewrite.servlet.RewriteFilter  : Loaded [1] org.ocpsoft.rewrite.servlet.spi.RequestCycleWrapper [org.ocpsoft.rewrite.servlet.impl.HttpRewriteRequestCycleWrapper<0>]
    2023-03-21 16:20:16.023  INFO 63251 --- [           main] o.ocpsoft.rewrite.servlet.RewriteFilter  : Loaded [1] org.ocpsoft.rewrite.spi.RewriteProvider [org.ocpsoft.rewrite.servlet.impl.DefaultHttpRewriteProvider<0>]
    2023-03-21 16:20:16.023  INFO 63251 --- [           main] o.ocpsoft.rewrite.servlet.RewriteFilter  : Loaded [1] org.ocpsoft.rewrite.servlet.spi.RewriteResultHandler [org.ocpsoft.rewrite.servlet.impl.HttpRewriteResultHandler<0>]
    2023-03-21 16:20:16.023  INFO 63251 --- [           main] o.ocpsoft.rewrite.servlet.RewriteFilter  : Loaded [1] org.ocpsoft.rewrite.servlet.spi.InboundRewriteProducer [org.ocpsoft.rewrite.servlet.impl.HttpInboundRewriteProducer<0>]
    2023-03-21 16:20:16.023  INFO 63251 --- [           main] o.ocpsoft.rewrite.servlet.RewriteFilter  : Loaded [1] org.ocpsoft.rewrite.servlet.spi.OutboundRewriteProducer [org.ocpsoft.rewrite.servlet.impl.HttpOutboundRewriteProducer<0>]
    2023-03-21 16:20:16.024  INFO 63251 --- [           main] o.ocpsoft.rewrite.servlet.RewriteFilter  : Loaded [1] org.ocpsoft.rewrite.servlet.spi.ContextListener [org.ocpsoft.rewrite.spring.SpringServiceEnricher<0>]
    2023-03-21 16:20:16.025  INFO 63251 --- [           main] o.ocpsoft.rewrite.servlet.RewriteFilter  : Loaded [0] org.ocpsoft.rewrite.servlet.spi.RequestListener []
    2023-03-21 16:20:16.026  INFO 63251 --- [           main] o.ocpsoft.rewrite.servlet.RewriteFilter  : Loaded [0] org.ocpsoft.rewrite.servlet.spi.RequestParameterProvider []
    2023-03-21 16:20:16.030  INFO 63251 --- [           main] o.ocpsoft.rewrite.servlet.RewriteFilter  : Loaded [2] org.ocpsoft.rewrite.el.spi.ExpressionLanguageProvider [org.ocpsoft.rewrite.spring.SpringExpressionLanguageProvider<20>, org.ocpsoft.rewrite.faces.FacesExpressionLanguageProvider<30>]
    2023-03-21 16:20:16.032  INFO 63251 --- [           main] o.ocpsoft.rewrite.servlet.RewriteFilter  : Loaded [1] org.ocpsoft.rewrite.spi.InvocationResultHandler [org.ocpsoft.rewrite.faces.NavigatingInvocationResultHandler<100>]
    2023-03-21 16:20:16.034  INFO 63251 --- [           main] o.ocpsoft.rewrite.servlet.RewriteFilter  : Loaded [2] org.ocpsoft.common.spi.ServiceEnricher [org.ocpsoft.rewrite.spring.SpringServiceEnricher<0>, org.joinfaces.autoconfigure.rewrite.SpringBootServiceEnricher]
    2023-03-21 16:20:16.036  INFO 63251 --- [           main] o.ocpsoft.rewrite.servlet.RewriteFilter  : Loaded [1] org.ocpsoft.rewrite.spi.ConfigurationCacheProvider [org.ocpsoft.rewrite.servlet.impl.ServletContextConfigurationCacheProvider<0>]
    2023-03-21 16:20:16.039  INFO 63251 --- [           main] o.ocpsoft.rewrite.servlet.RewriteFilter  : Loaded [2] org.ocpsoft.rewrite.config.ConfigurationProvider [org.joinfaces.autoconfigure.rewrite.SpringBootAnnotationConfigProvider<100>, org.ocpsoft.rewrite.annotation.config.AnnotationConfigProvider<100>]
    2023-03-21 16:20:16.042  INFO 63251 --- [           main] o.o.r.s.impl.DefaultHttpRewriteProvider  : Loaded [0] org.ocpsoft.rewrite.spi.RuleCacheProvider []
    2023-03-21 16:20:16.452  INFO 63251 --- [           main] o.o.rewrite.param.DefaultParameterStore  : Loaded [1] org.ocpsoft.rewrite.spi.GlobalParameterProvider [org.ocpsoft.rewrite.instance.WildcardParameterProvider<0>]
    2023-03-21 16:20:16.480  INFO 63251 --- [           main] o.ocpsoft.rewrite.servlet.RewriteFilter  : Rewrite 4.0.0-SNAPSHOT initialized.
    2023-03-21 16:20:16.714  INFO 63251 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
    2023-03-21 16:20:16.721  INFO 63251 --- [           main] com.example.rewrite.RewriteApplication   : Started RewriteApplication in 2.557 seconds (JVM running for 2.778)
    
  20. lincolnthree commented on Mar 21, 2023

    @lincolnthree
    Member

    Additionally. I have improved the expression language bean name resolution so that it tries providers until either it finds one that works, or they all fail.

  21. lincolnthree commented on Mar 21, 2023

    @lincolnthree
    Member

    @larsgrefer I believe I have resolved this. Please review the pull request if you have some time :) I'll release a new version soon if you approve - #368

    @TobiasBerndt You should be able to try the changes if you clone my fork and run mvn clean install or mvn clean install -DskipTests=true if you want to skip the tests. Then just update your project to use the 4.0.0-SNAPSHOT version of Rewrite. Let me know if it works?

  22. TobiasBerndt commented on Mar 22, 2023

    @TobiasBerndt
    Author

    I tested the changes successfully with 4.0.0-SNAPSHOT as JAR and WAR.
    Thank you @lincolnthree and @larsgrefer.
    I'm looking forward to the new release. :)

  23. lincolnthree commented on Apr 11, 2023

    @lincolnthree
    Member

    Thanks for confirming, @TobiasBerndt - Apologies for the delay in moving forward with this. The past few weeks went off the rails. I am working on getting this PR merged with @larsgrefer's changes, and pulled into the other release tracks/branches as well.

  24. TobiasBerndt commented on Aug 16, 2023

    @TobiasBerndt
    Author

    Hi @lincolnthree, now I lost also track on this 😊
    But to resume the topic do you think you have time to get the changes released?

  25. lincolnthree commented on Aug 22, 2023

    @lincolnthree
    Member

    Hey @TobiasBerndt - Yeah, there are a number of pending updates that I need to get merged into the three primary branches. This is one of them. Sorry for the delay. Trying to make some time in the next week. Are you blocked by this currently, or can you use the local build temporarily?

  26. TobiasBerndt commented on Aug 23, 2023

    @TobiasBerndt
    Author

    I'm not blocked right now as I have a workaround by not using 3.5.1.Final and staying on 3.4.4.Final
    But I want to upgrade to Spring Boot 3.x.x in near future and as far as I can see here (https://github.com/joinfaces/joinfaces#system-requirements) I need to upgrade also to new Joinfaces version and I don't know if currently used Rewrite version will then be incompatible.

  27. larsgrefer commented on Aug 23, 2023

    @larsgrefer
    Contributor

    @TobiasBerndt Joinfaces 5.x currently includes Rewrite 6.0.0.Alpha1: https://docs.joinfaces.org/5.1.x/reference/#versions

  28. lincolnthree commented on Oct 4, 2023

    @lincolnthree
    Member

    Please try the new Final versions that have been released today:

    Rewrite versions 8.0.0, 9.0.0, and 10.0.0 correspond with Jakarta EE 8, 9, and 10, respectively.

    image

  29. lincolnthree commented on Oct 4, 2023

    @lincolnthree
    Member

    Note. This issue may still require more work, and I am still planning on merging the Spring Boot improvements in PR #375

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions