[ 
https://issues.apache.org/jira/browse/TAP5-2776?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17841159#comment-17841159
 ] 

Roman Trapickin edited comment on TAP5-2776 at 4/26/24 11:18 AM:
-----------------------------------------------------------------

As promised, here are the code snippets from our Tapestry Spring Boot setup 
(simplified for better readability):
{code:java|title=TapestrySpringBootFilter.java}
@Override
public void init(FilterConfig config) throws ServletException {
  ((ConfigurableApplicationContext) WebApplicationContextUtils
      .getRequiredWebApplicationContext(config.getServletContext()))
          .addBeanFactoryPostProcessor(this::delayedInit);
}
private void delayedInit(ConfigurableListableBeanFactory beanFactory) {
  // ...
  registry.performRegistryStartup();
  appInitializer.announceStartup();
  registry.cleanupThread();
}
// the rest is almost identical to TapestryFilter
{code}
{code:java|title=TapestrySpringBootModuleDef.java}
ObjectProvider springBeanProvider = new ObjectProvider() {
    @Override
    public <T> T provide(Class<T> t, AnnotationProvider p, ObjectLocator l) {
      Map<String, T> beanMap = WebApplicationContextUtils
          .getRequiredWebApplicationContext(servletContext)
          .getBeansOfType(t);
      switch (beanMap.size()) {
        case 0:
          return null;
        case 1:
          return t.cast(beanMap.values().iterator().next());
        // ... 
      }
    }
};
// The rest is very similar to SpringModuleDef
{code}

Please let me know if you need any further information.


was (Author: JIRAUSER305242):
As promised, here are the code snippets from our Tapestry Spring Boot setup 
(simplified for better readability):
{code:java|title=TapestrySpringBootFilter.java}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
  ((ConfigurableApplicationContext) WebApplicationContextUtils
      .getRequiredWebApplicationContext(config.getServletContext()))
          .addBeanFactoryPostProcessor(this::delayedInit);
}
private void delayedInit(ConfigurableListableBeanFactory beanFactory) {
  // ...
  registry.performRegistryStartup();
  appInitializer.announceStartup();
  registry.cleanupThread();
}
// the rest is almost identical to TapestryFilter
{code}
{code:java|title=TapestrySpringBootFilter.java}
ObjectProvider springBeanProvider = new ObjectProvider() {
    @Override
    public <T> T provide(Class<T> t, AnnotationProvider p, ObjectLocator l) {
      Map<String, T> beanMap = WebApplicationContextUtils
          .getRequiredWebApplicationContext(servletContext)
          .getBeansOfType(t);
      switch (beanMap.size()) {
        case 0:
          return null;
        case 1:
          return t.cast(beanMap.values().iterator().next());
        // ... 
      }
    }
};
{code}

Please let me know if you need any further information.

> Make page preloading optional in production mode
> ------------------------------------------------
>
>                 Key: TAP5-2776
>                 URL: https://issues.apache.org/jira/browse/TAP5-2776
>             Project: Tapestry 5
>          Issue Type: Bug
>          Components: tapestry-core
>    Affects Versions: 5.8.5, 5.8.6
>            Reporter: Roman Trapickin
>            Priority: Major
>
> We use Tapestry 5.8.4 and Spring Boot 2.7 in production. To make things work, 
> Tapestry context is initialized by the Spring context, not vice versa as done 
> by {{tapestry-spring}}. This a tricky situation since Tapestry needs Spring 
> beans and Spring beans sometimes need Tapestry beans.
> To solve this problem we exploit Spring's BeanFactoryPostProcessor in order 
> to initialize Tapestry context before Spring beans are evaluated:
> # Start initializing Spring context
> # "Pause" within BeanFactoryPostProcessor and initialize Tapestry context. 
> Tapestry beans do not need fully initialized Spring beans yet.
> # Finish Spring context initialization.
> # Tapestry beans and pages can now inject fully initialized Spring beans.
> I'll provide some code snippets in the comments below.
> TAP5-2772 has changed the preloading behavior in production mode so that 
> Tapestry now eagerly resolves the Spring beans, thus relying on a fully 
> initialized Spring context. Since Spring context init is not finished yet, a 
> good amount of unresolved bean/property exceptions is thrown. Now we cannot 
> break this vicious cycle of both contexts having a need for each other. This 
> problem is not present in development mode.
> I file this issue as a bug since we need the old behavior to be restored in 
> production mode. Alternatively we could introduce a setting for production 
> mode to disable the new preloading feature.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to