Uploaded image for project: 'Spring Web Flow'
  1. Spring Web Flow
  2. SWF-1713

ClassNotFoundException (backwards compatibility issue)

    XMLWordPrintable

    Details

      Description

      Upgrading to Spring (Context) v 4.3.X breaks backwards compatibility in Spring WebFlow.

      The following commit upgrades from 4.2.X to 4.3.X:
      Update minor versions of dependencies (commit 0dc8b52c72696ade87c59c1f79c6c107fae9fb53)

      Spring context changed between 4.2.X and 4.3.X, particularly https://jira.spring.io/browse/SPR-14626 gave rise to a change in GenericApplicationContext where the ResourceLoader is now also being used as a class loader.
      This behaviour can be made backwards compatible by setting a custom class loader - e.g. the same class loader as previously.

          // from spring context
      	@Override
      	public ClassLoader getClassLoader() {
              // this is new and is causes backwards compatability issues for spring webflow
      		if (this.resourceLoader != null && !this.customClassLoader) {
      			return this.resourceLoader.getClassLoader();
      		}
              
              // usually this would get called directly
      		return super.getClassLoader();
      	}
      

      Asumme you have a multi class loader environment
      WebApp (contains code and flow xml)
      Server (contains spring and spring-webflow)

      In FlowModelFlowBuilder, the ResourceLoader is set (which incidentally overrides the class loader in spring (context) 4.3.X):

      flowContext.setResourceLoader(new FlowRelativeResourceLoader(flowResource));
      

      This will of course cause a ClassNotFoundException to be thrown when trying to load domain classes.
      This is due to the fact that in the project setup, the webflow code is in another classloader than the domain code.

      To be backwards compatible, the fix is quite simple - we need to memoize the classLoader, before overriding it with the resource loader

      // memoize class loader
      final ClassLoader classLoader = flowContext.getClassLoader();
      Resource flowResource = flowModelHolder.getFlowModelResource();
      flowContext.setResourceLoader(new FlowRelativeResourceLoader(flowResource));
      // restore class loader
      flowContext.setClassLoader(classLoader);
      

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              rstoya05-aop Rossen Stoyanchev
              Reporter:
              taa@autorola.com Thomas Ã…kerman
              Votes:
              1 Vote for this issue
              Watchers:
              4 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: