OpenLiberty / open-liberty

Open Liberty is a highly composable, fast to start, dynamic application server runtime environment
https://openliberty.io
Eclipse Public License 2.0
1.13k stars 578 forks source link

Reduce CWNEN0047W / CWNEN0049W Resource Annotation Warnings for JSF for Some Scenarios #27951

Closed volosied closed 3 months ago

volosied commented 3 months ago

Describe the bug
Resource Annotation Scanning can encounter NoClassDefFoundError errors.

For example:

Stack Dump = java.lang.NoClassDefFoundError: org.apache.tiles.el.ScopeELResolver
    at java.base/java.lang.J9VMInternals.prepareClassImpl(Native Method)
    at java.base/java.lang.J9VMInternals.prepare(J9VMInternals.java:361)
    at java.base/java.lang.Class.getDeclaredFields(Class.java:982)
    at com.ibm.ws.injectionengine.InjectionProcessorManager.getAllDeclaredFields(InjectionProcessorManager.java:392)
    at com.ibm.ws.injectionengine.InjectionProcessorManager.processAnnotations(InjectionProcessorManager.java:217)
    at com.ibm.ws.injectionengine.AbstractInjectionEngine.processInjectionMetaData(AbstractInjectionEngine.java:482)
    at com.ibm.ws.injectionengine.osgi.internal.OSGiInjectionEngineImpl.processInjectionMetaData(OSGiInjectionEngineImpl.java:242)
    at com.ibm.ws.injectionengine.ReferenceContextImpl.processImpl(ReferenceContextImpl.java:590)
    at com.ibm.ws.injectionengine.ReferenceContextImpl.process(ReferenceContextImpl.java:289)
    at com.ibm.ws.injectionengine.osgi.internal.OSGiReferenceContextImpl.process(OSGiReferenceContextImpl.java:32)
    at com.ibm.ws.webcontainer.osgi.webapp.WebApp.commonInitializationStart(WebApp.java:254)
    at com.ibm.ws.webcontainer.webapp.WebApp.initialize(WebApp.java:1035)

Steps to Reproduce
If the applications bundles a library, Liberty may try to scan for resource annotations. However, some libraries have optional classes, and these would still be searched by JSF. Optional classes often require extra libraries (which aren't bundled in the app), and therefore would cause liberty to provide a FFDC for the NoClassDefFoundError.

These classes searched for resources extend some EL / JSF API classes / interfaces. A list can be found here.

Expected behavior
These warnings typically valid, but not in all scenarios. One workaround is to simply add the library which contains the missing class.

Diagnostic information:

Additional context
https://github.com/OpenLiberty/open-liberty/blob/a0f4167ee6dfad2d80a420d32ea410d4df239542/dev/com.ibm.ws.jsf.shared/src/com/ibm/ws/jsf/shared/util/JSFInjectionClassListCollaborator.java#L137-L156

Link to a copy of the TileConfigurator: https://github.com/joshlong-attic/spring-framework/blob/master/spring-webmvc-tiles3/src/main/java/org/springframework/web/servlet/view/tiles3/TilesConfigurer.java#L414

I don't think it's possible to avoid all these errors since they are typically valid. However, I think it's safe to avoid searching nested classes.

FFDC / Warnings : https://github.com/OpenLiberty/open-liberty/blob/0b6910ae74a52722309f65d74027389c2bdfa6c5/dev/com.ibm.ws.injection.core/src/com/ibm/ws/injectionengine/InjectionProcessorManager.java#L395

volosied commented 3 months ago

This is isn't really a bug? Or should I keep the label? More of an improvement...?

volosied commented 3 months ago

Our investigation showed that the "javax.el.ELResolver" is eligible for injection as mandated by the specification: https://jakarta.ee/specifications/faces/3.0/jakarta-faces-3.0#jakarta-faces-managed-classes-and-jakarta-ee-annotations (Faces 3.0 linked, but it applies to 2.3, 2.2, etc)

This is particular case the code is:

private static class CompositeELResolverImpl extends CompositeELResolver {
public CompositeELResolverImpl() {
            add(new ScopeELResolver()); // <--- not on classpath 
            ...

This means that CompositeELResolverImpl is of type ELResolver and the class should be searched for resources and injections. Our team has decided that it is best not to touch this code. Perhaps this could be addressed via a spec issue (prohibit private nested classes to be searched).

However, the best workaround is to include the required classes on the classpath, unfortunately.