Announcement Announcement Module
No announcement yet.
Classpath problem using SingletonBeanFactoryLocator Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Classpath problem using SingletonBeanFactoryLocator

    Hi all,

    I'm experience problems using the SingletonBeanFactoryLocator, which I suspect are coming from my packaging.

    My EAR contains many JAR files: core.jar, server.jar, web.jar and all dependent libraries. Within core.jar exists a class, SingletonApplicationContextProvider, which calls SingletonBeanFactoryLocator.useBeanFactory("beanFa ctoryReference") to build an ApplicationContext. Within server.jar exist both beanRefFactory.xml and applicationContext.xml, the first including a reference to the second.

    I get the following error when first calling the SingletonBeanFactoryLocator:

    org.springframework.beans.FatalBeanException: Unable to find resource for specified definition. Group resource name [classpath*:beanRefFactory.xml], factory key [beanFactoryReference]
    	at org.springframework.beans.factory.access.SingletonBeanFactoryLocator.createDefinition(
    	at org.springframework.beans.factory.access.SingletonBeanFactoryLocator.useBeanFactory(
    	at core.context.SingletonApplicationContextProvider.getApplicationContext(
    	at promo.web.LoginAction.<init>(
    	at java.lang.Class.newInstance0(Native Method)
    	at java.lang.Class.newInstance(
    	at org.apache.struts.util.RequestUtils.applicationInstance(
    	at org.apache.struts.action.RequestProcessor.processActionCreate(
    	at org.apache.struts.action.RequestProcessor.process(
    	at promo.web.PromoRequestProcessor.process(
    	at org.apache.struts.action.ActionServlet.process(
    	at org.apache.struts.action.ActionServlet.doGet(
    	at javax.servlet.http.HttpServlet.service(
    	at javax.servlet.http.HttpServlet.service(
    	at com.evermind.server.http.ResourceFilterChain.doFilter(
    	at com.evermind.server.http.ServletRequestDispatcher.invoke(
    	at com.evermind.server.http.ServletRequestDispatcher.forwardInternal(
    	at com.evermind.server.http.ServletRequestDispatcher.forward(
    	at com.evermind.server.http.GetParametersRequestDispatcher.forward(
    	at promo.web.filters.FirstRedirector.doFilter(
    	at com.evermind.server.http.FileRequestDispatcher.handleWithFilter(
    	at com.evermind.server.http.FileRequestDispatcher.forwardInternal(
    	at com.evermind.server.http.HttpRequestHandler.processRequest(
    This works fine on Tomcat 5.5.17 but fails on OC4J 9.0.4. Spring 2.0 RC1 and Struts 1.2.9 are being used.

    Any idea why this isn't working? I don't have much hair left on my head now


  • #2
    "classpath*:" looks suspicious
    I'm not sure how it's handled by different classloaders, but in my experience it didn't work well everywhere.

    So, I would replace that with something of "lower-level", so try specifying the the expluicit classpath to your beanRefFactory.xml.


    • #3
      one issue with classpath* is that it relies on the existing classloading infrastructure for resource loading which differs from server to server - i.e. Tomcat has its own implementation and so does oc4j.
      classpath*: beanRef will only look for the xml inside unpacked jars (i.e. it will not look into jars). See the javadoc for PathMatchingResourcePatternResolver:
      Implications on portability:
      If the specified path is already a file URL (either explicitly, or implicitly because the base ResourceLoader is a filesystem one, then wildcarding is guaranteed to work in a completely poratable fashion.
      If the specified path is a classpath location, then the resolver must obtain the last non-wildcard path segment URL via a Classloader.getResource() call. Since this is just a node of the path (not the file at the end) it is actually undefined (in the ClassLoader Javadocs) exactly what sort of a URL is returned in this case. In practice, it is always a representing the directory, where the classpath resource resolves to a filesystem location, or a jar URL of some sort, where the classpath resource resolves to a jar location. Still, there is a portability concern on this operation.
      If a jar URL is obtained for the last non-wildcard segment, the resolver must be able to get a from it, or manually parse the jar URL, to be able to walk the contents of the jar, and resolve the wildcard. This will work in most environments, but will fail in others, and it is strongly recommended that the wildcard resolution of resources coming from jars be thoroughly tested in your specific environment before you rely on it.
      classpath*: Prefix:
      There is special support for retrieving multiple class path resources with the same name, via the "classpath*:" prefix. For example, "classpath*:META-INF/beans.xml" will find all "beans.xml" files in the class path, be it in "classes" directories or in JAR files. This is particularly useful for autodetecting config files of the same name at the same location within each jar file. Internally, this happens via a ClassLoader.getResources() call, and is completely portable.
      The "classpath*:" prefix can also be combined with a PathMatcher pattern in the rest of the location path, for example "classpath*:META-INF/*-beans.xml". In this case, the resolution strategy is fairly simple: a ClassLoader.getResources() call is used on the last non-wildcard path segment to get all the matching resources in the class loader hierarchy, and then off each resource the same PathMatcher resoltion strategy described above is used for the wildcard subpath.
      Other Notes:
      WARNING: Note that "classpath*:" when combined with Ant-style patterns will only work reliably with at least one root directory before the pattern starts, unless the actual target files reside in the file system. This means that a pattern like "classpath*:*.xml" will not retrieve files from the root of jar files but rather only from the root of expanded directories. This originates from a limitation in the JDK's ClassLoader.getResources() method which only returns file system locations for a passed-in empty String (indicating potential roots to search).
      WARNING: Ant-style patterns with "classpath:" resources are not guaranteed to find matching resources if the root package to search is available in multiple class path locations. This is because a resource such as
      may be in only one location, but when a path such as classpath:com/mycompany/**/service-context.xml
      is used to try to resolve it, the resolver will work off the (first) URL returned by getResource("com/mycompany");. If this base package node exists in multiple classloader locations, the actual end resource may not be underneath. Therefore, preferably, use "classpath*:" with the same Ant-style pattern in such a case, which will search all class path locations that contain the root package.