Skip to content

Component scanning does not find sub-packages in EAR on Weblogic 12.2.x [SPR-14187] #18758

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
spring-projects-issues opened this issue Apr 18, 2016 · 11 comments
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: bulk-closed An outdated, unresolved issue that's closed in bulk as part of a cleaning process

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Apr 18, 2016

Robson Vargas Farias opened SPR-14187 and commented

I've an EAR application which contains a simple message-driven bean that receive data from a queue on weblogic; this MDB is intercepted by SpringBeanAutowiringInterceptor in order to inject a @Autowired bean, but, I'm receiving an exception:

Caused By: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.test.beans.bo.SampleBO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

My configuration is:

<context:component-scan base-package="com.test.beans" />

The strange is: if I change the base package to the exactly package where my bean is on it works fine. Sample:

<context:component-scan base-package="com.test.beans.bo" />

Suggesting that the issue is related to the sub-packages scanning.

my ref context:

<beans
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<bean id="myContext" class="org.springframework.context.support.ClassPathXmlApplicationContext">
		<constructor-arg value="/META-INF/app-config.xml" />
	</bean>
</beans>

my app config:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" 
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
	http://www.springframework.org/schema/tx      http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/util    http://www.springframework.org/schema/util/spring-util-4.0.xsd
	http://www.springframework.org/schema/task    http://www.springframework.org/schema/task/spring-task-4.0.xsd">

	<context:annotation-config />
	<context:component-scan base-package="com.test.beans" />

</beans>

Tested on: Weblogic version: 12.2.x and lastest versions of Spring 4.x and 5.x (as shared libraries)


Affects: 4.1.7

Issue Links:

1 votes, 4 watchers

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

Could it be that you have several jars containing com.test.beans? Depending on the class loader in use, you might only see the 'first' occurence of that base package then, with classes and sub-packages only being found in there... You can enforce scanning the entire class path through specifying classpath*:com.test.beans; does that help in your scenario?

@spring-projects-issues
Copy link
Collaborator Author

Robson Vargas Farias commented

Hi, yes, I have some jars containing same base package-base. I've just tried:

<context:component-scan base-package="classpath*:com.test.beans" />

but, didn´t works.

I've checked that the content from the variable resolvableDependencies (on DefaultListableBeanFactory class) does not contains the instances loaded.

@spring-projects-issues
Copy link
Collaborator Author

Robson Vargas Farias commented

honestly, I strip my application (other jars with same package, removed third-part jars, removed all other spring configs, etc.) and keep only the enough files (MDB and the injectable bean) to run it and still doesnt work.

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

The problem is not in DefaultListableBeanFactory though; resolvableDependencies is a special-purpose field, not the complete set of potential targets. You'd rather have to debug into PathMatchingResourcePatternResolver when it traverses the base packages and tries to go into sub-directories...

@spring-projects-issues
Copy link
Collaborator Author

Robson Vargas Farias commented

@Juergen,

I found the problem but not sure about the solution yet, see:

for this class.method: PatchMatchingResourcePatternResolver.findAllClassPathResources weblogic is returning a weblogic.utils.classloaders.ResourceEnumeration value from its class loader (weblogic.utils.classloaders.GenericClassLoader) and this one is not able to load the path "com/test/beans/", hence there is no elements in resourceUrls variable (i.e. resourceUrls.hasMoreElements() = false).

is this helpful ?

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

If that is the case, then WebLogic's ClassLoader implementation does not support the retrieval of such base packages (possibly since it is empty and just contains subdirectories but no actual resources)? I'm afraid you'll have to specify all your concrete subpackages manually then (or potentially put a dummy class in the base package?). In any case, Spring's classpath scanning can only work as well as a particular ClassLoader allows it to; it is fundamentally a best-effort feature. We are going the extra mile where we can, for example supporting JBoss VFS explicitly... but we might be out of luck for arrangements such as yours on WebLogic if the given ClassLoader simply does not expose the necessary information to us.

@spring-projects-issues
Copy link
Collaborator Author

Robson Vargas Farias commented

I did several tests and I can confirm that the problem is with the Weblogic's 12c ClassLoader, also, I did a test using a +local code+ (which uses sun.misc.CompoundEnumeration enumeration from LauncherAPP ClassLoader and it works fine once I have some resources into subdirectories(@Component and @Repository)).

I'll open a SR on Oracle Metalink in order to get them a clarification about this issue and keep you in touch.

@spring-projects-issues
Copy link
Collaborator Author

Robson Vargas Farias commented

btw, I've here another important input:

if I put the below code on my "onMessage" method from my MDB, it result in a good enumeration with elements.

Enumeration<URL> resourceUrls = Thread.currentThread().getContextClassLoader().getResources("com/test/beans/");
          while (resourceUrls.hasMoreElements()) {
              URL url = resourceUrls.nextElement();
              System.out.println(new UrlResource(url));
          }

but, the spring side code, which uses ClassLoader *from org.springframework.context.support.ClassPathXmlApplicationContext *in PatchMatchingResourcePatternResolver via getClassLoader method does not working (resourceUrls.hasMoreElements() = false):

protected Resource[] findAllClassPathResources(String location) throws IOException {
     String path = location;
     if (path.startsWith("/")) {
          path = path.substring(1);
     }
     ClassLoader cl = getClassLoader();
     Enumeration<URL> resourceUrls = (cl != null ? cl.getResources(path) : ClassLoader.getSystemResources(path));
     Set<Resource> result = new LinkedHashSet<Resource>(16);
     while (resourceUrls.hasMoreElements()) {
          URL url = resourceUrls.nextElement();
          result.add(convertClassLoaderURL(url));
     }
     return result.toArray(new Resource[result.size()]);
}

for both the same ClassLoader is loaded..

weblogic.utils.classloaders.GenericClassLoader@xpto finder: weblogic.utils.classloaders.CodeGenClassFinder@xpto annotation: TestAPP@

@spring-projects-issues
Copy link
Collaborator Author

Lorenzo Gatti commented

Any update for this issue? Is there any workaround?

@spring-projects-issues
Copy link
Collaborator Author

Lorenzo Gatti commented

For others with the same problem: put a java class (simple, not a spring bean) in the root package permits to the classloader to retrieve the jar.

@spring-projects-issues spring-projects-issues added type: bug A general bug status: waiting-for-triage An issue we've not yet triaged or decided on in: core Issues in core modules (aop, beans, core, context, expression) and removed type: bug A general bug labels Jan 11, 2019
@rstoyanchev rstoyanchev added status: bulk-closed An outdated, unresolved issue that's closed in bulk as part of a cleaning process and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Jan 11, 2019
@spring-projects-issues
Copy link
Collaborator Author

Bulk closing outdated, unresolved issues. Please, reopen if still relevant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: bulk-closed An outdated, unresolved issue that's closed in bulk as part of a cleaning process
Projects
None yet
Development

No branches or pull requests

2 participants