From 2e7fe2a0c1bd5ff6b07ee1db30fd4c78b1a150ea Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Mon, 20 Nov 2023 10:03:04 +0100 Subject: [PATCH] feat(#TOMEE-4281): Better logging we can't load an application class --- .../openejb/config/AnnotationDeployer.java | 93 ++++++++++++------- .../openejb/config/rules/Messages.properties | 8 +- .../config/rules/Messages_hi.properties | 8 +- 3 files changed, 70 insertions(+), 39 deletions(-) diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java b/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java index aa00627d270..1f5beda408c 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java @@ -2059,8 +2059,12 @@ public ClientModule deploy(final ClientModule clientModule) throws OpenEJBExcept final AnnotationFinder annotationFinder = createFinder(clazz); buildAnnotatedRefs(client, annotationFinder, classLoader); - } catch (final ClassNotFoundException e) { - /** + } catch (final ClassNotFoundException | NoClassDefFoundError e) { + + logger.debug("Could not load main class {1} for client module {2} / {3}", + className, clientModule.getJarLocation(), clientModule.getFile().getName()); + + /* * Some ClientModule are discovered only because the jar uses a Main-Class * entry in the MANIFEST.MF file. Lots of jars do this that are not used as * java ee application clients, so lets not make this a failure unless it @@ -2081,7 +2085,10 @@ public ClientModule deploy(final ClientModule clientModule) throws OpenEJBExcept try { clazz = classLoader.loadClass(className); remoteClients.add(clazz); - } catch (final ClassNotFoundException e) { + } catch (final ClassNotFoundException | NoClassDefFoundError e) { + logger.debug("Could not load RemoteClient class {1} for client module {2} / {3}", + className, clientModule.getJarLocation(), clientModule.getFile().getName()); + throw new OpenEJBException("Unable to load RemoteClient class: " + className, e); } @@ -2095,7 +2102,9 @@ public ClientModule deploy(final ClientModule clientModule) throws OpenEJBExcept final Class clazz; try { clazz = classLoader.loadClass(className); - } catch (final ClassNotFoundException e) { + } catch (final ClassNotFoundException | NoClassDefFoundError e) { + logger.debug("Could not load LocalClient class {1} for client module {2} / {3}", + className, clientModule.getJarLocation(), clientModule.getFile().getName()); throw new OpenEJBException("Unable to load LocalClient class: " + className, e); } @@ -2224,7 +2233,9 @@ public WebModule deploy(final WebModule webModule) throws OpenEJBException { try { clazz = classLoader.loadClass(application); classes.add(clazz); - } catch (final ClassNotFoundException e) { + } catch (final ClassNotFoundException | NoClassDefFoundError e) { + logger.debug("Could not load rest Application class {1} for module {2} / {3}", + application, webModule.getJarLocation(), webModule.getFile().getName()); throw new OpenEJBException("Unable to load Application class: " + application, e); } if (Modifier.isAbstract(clazz.getModifiers())) { @@ -2296,7 +2307,9 @@ public WebModule deploy(final WebModule webModule) throws OpenEJBException { if (servlet.getServletClass() == null) { servlet.setServletClass(servletClass); } - } catch (final ClassNotFoundException e) { + } catch (final ClassNotFoundException | NoClassDefFoundError e) { + logger.debug("Could not load Servlet class {1} for web module {2} / {3}", + servletClass, webModule.getJarLocation(), webModule.getFile().getName()); if (servlet.getServletClass() != null) { throw new OpenEJBException("Unable to load servlet class: " + servletClass, e); } else { @@ -2325,7 +2338,9 @@ public WebModule deploy(final WebModule webModule) throws OpenEJBException { try { final Class clazz = classLoader.loadClass(filterClass); classes.add(clazz); - } catch (final ClassNotFoundException e) { + } catch (final ClassNotFoundException | NoClassDefFoundError e) { + logger.debug("Could not load Servlet Filter class {1} for web module {2} / {3}", + filterClass, webModule.getJarLocation(), webModule.getFile().getName()); throw new OpenEJBException("Unable to load servlet filter class: " + filterClass, e); } } @@ -2340,7 +2355,9 @@ public WebModule deploy(final WebModule webModule) throws OpenEJBException { try { final Class clazz = classLoader.loadClass(listenerClass); classes.add(clazz); - } catch (final ClassNotFoundException e) { + } catch (final ClassNotFoundException | NoClassDefFoundError e) { + logger.debug("Could not load Servlet listener class {1} for web module {2} / {3}", + listenerClass, webModule.getJarLocation(), webModule.getFile().getName()); throw new OpenEJBException("Unable to load servlet listener class: " + listenerClass, e); } } @@ -2356,7 +2373,9 @@ public WebModule deploy(final WebModule webModule) throws OpenEJBException { try { final Class clazz = classLoader.loadClass(listenerClass); classes.add(clazz); - } catch (final ClassNotFoundException e) { + } catch (final ClassNotFoundException | NoClassDefFoundError e) { + logger.debug("Could not load TagLib listener class {1} for web module {2} / {3}", + listenerClass, webModule.getJarLocation(), webModule.getFile().getName()); logger.error("Unable to load tag library servlet listener class: " + listenerClass); } } @@ -2371,7 +2390,9 @@ public WebModule deploy(final WebModule webModule) throws OpenEJBException { try { final Class clazz = classLoader.loadClass(tagClass); classes.add(clazz); - } catch (final ClassNotFoundException e) { + } catch (final ClassNotFoundException | NoClassDefFoundError e) { + logger.debug("Could not load tag class {1} for web module {2} / {3}", + tagClass, webModule.getJarLocation(), webModule.getFile().getName()); logger.error("Unable to load tag library tag class: " + tagClass); } } @@ -2399,7 +2420,9 @@ public WebModule deploy(final WebModule webModule) throws OpenEJBException { try { final Class clazz = classLoader.loadClass(handlerClass); classes.add(clazz); - } catch (final ClassNotFoundException e) { + } catch (final ClassNotFoundException | NoClassDefFoundError e) { + logger.debug("Could not load web service handler class {1} for web module {2} / {3}", + handlerClass, webModule.getJarLocation(), webModule.getFile().getName()); throw new OpenEJBException("Unable to load webservice handler class: " + handlerClass, e); } } @@ -2419,7 +2442,9 @@ public WebModule deploy(final WebModule webModule) throws OpenEJBException { try { final Class clazz = classLoader.loadClass(managedBeanClass); classes.add(clazz); - } catch (final ClassNotFoundException e) { + } catch (final ClassNotFoundException | NoClassDefFoundError e) { + logger.debug("Could not load Faces managed bean class {1} for web module {2} / {3}", + managedBeanClass, webModule.getJarLocation(), webModule.getFile().getName()); logger.error("Unable to load JSF managed bean class: " + managedBeanClass); } } @@ -2969,6 +2994,9 @@ public EjbModule deploy(final EjbModule ejbModule) throws OpenEJBException { try { clazz = classLoader.loadClass(realClassName(interceptor.getInterceptorClass())); } catch (final ClassNotFoundException e) { + logger.debug("Could not load interceptor class {1} for enterprise beans module {2} / {3}", + interceptor.getInterceptorClass(), ejbModule.getJarLocation(), ejbModule.getFile().getName()); + throw new OpenEJBException("Unable to load interceptor class: " + interceptor.getInterceptorClass(), e); } @@ -3012,7 +3040,7 @@ public EjbModule deploy(final EjbModule ejbModule) throws OpenEJBException { processWebServiceClientHandlers(interceptor, annotationFinder, classLoader); - /** + /* * Interceptors do not have their own section in ejb-jar.xml for resource references * so we add them to the references of each ejb. A bit backwards but more or less * mandated by the design of the spec. @@ -3116,7 +3144,7 @@ private void processSessionInterfaces(final SessionBean sessionBean, final Class sessionBean.setLocalBean(new Empty()); } - /** + /* * Anything declared as both and is invalid in strict mode */ if (strict) { @@ -3127,7 +3155,7 @@ private void processSessionInterfaces(final SessionBean sessionBean, final Class } } - /** + /* * Merge the xml declared business interfaces into the complete set */ final BusinessInterfaces all = new BusinessInterfaces(); @@ -3195,15 +3223,15 @@ private void processSessionInterfaces(final SessionBean sessionBean, final Class } } - /** - * Anything discovered and delcared in a previous loop + /* + * Anything discovered and declared in a previous loop * or at the beginning in the deployment descriptor is - * not eligable to be redefined. + * not eligible to be redefined. */ interfaces.removeAll(all.local); interfaces.removeAll(all.remote); - /** + /* * OK, now start checking the class metadata */ final Local local = clazz.getAnnotation(Local.class); @@ -3212,7 +3240,7 @@ private void processSessionInterfaces(final SessionBean sessionBean, final Class final boolean impliedLocal = local != null && local.value().length == 0; final boolean impliedRemote = remote != null && remote.value().length == 0; - /** + /* * This set holds the values of @Local and @Remote * when applied to the bean class itself * @@ -3235,7 +3263,7 @@ private void processSessionInterfaces(final SessionBean sessionBean, final Class } } - /** + /* * Anything listed explicitly via @Local or @Remote * on the bean class does not need to be investigated. * We do not need to check these interfaces for @Local or @Remote @@ -3245,7 +3273,7 @@ private void processSessionInterfaces(final SessionBean sessionBean, final Class if (impliedLocal || impliedRemote) { if (interfaces.size() != 1) { - /** + /* * Cannot imply either @Local or @Remote and list multiple interfaces */ // Need to extract the class names and append .class to them to show proper validation level 3 message @@ -3261,21 +3289,21 @@ private void processSessionInterfaces(final SessionBean sessionBean, final Class // we don't go out to let be deployed } else if (impliedLocal) { validation.fail(ejbName, "ann.local.noAttributes", Join.join(", ", interfaceNames)); - /** + /* * This bean is invalid, so do not bother looking at the other interfaces or the superclass */ return; } if (impliedRemote) { validation.fail(ejbName, "ann.remote.noAttributes", Join.join(", ", interfaceNames)); - /** + /* * This bean is invalid, so do not bother looking at the other interfaces or the superclass */ return; } } else if (strict && impliedLocal && impliedRemote) { final Class interfce = interfaces.remove(0); - /** + /* * Cannot imply @Local and @Remote at the same time with strict mode on */ validation.fail(ejbName, "ann.localRemote.ambiguous", interfce.getName()); @@ -4120,7 +4148,7 @@ private void buildEjbRef(final JndiConsumer consumer, final EJB ejb, final Membe // TODO: Looks like we aren't looking for an existing ejb-ref or ejb-local-ref // we need to do this to support overriding. - /** + /* * Was @EJB used at a class level witout specifying the 'name' or 'beanInterface' attributes? */ final String name = consumer.getJndiConsumerName(); @@ -4342,7 +4370,7 @@ private void fail(final String component, final String key, final Object... deta */ private void buildResource(final JndiConsumer consumer, final Resource resource, final Member member) { - /** + /* * Was @Resource used at a class level without specifying the 'name' or 'beanInterface' attributes? */ if (member == null) { @@ -4363,7 +4391,7 @@ private void buildResource(final JndiConsumer consumer, final Resource resource, JndiReference reference = consumer.getEnvEntryMap().get(refName); if (reference == null) { - /** + /* * Was @Resource mistakenly used when either @PersistenceContext or @PersistenceUnit should have been used? */ if (member != null) { // Little quick validation for common mistake @@ -4657,7 +4685,7 @@ private void buildPersistenceContext(final JndiConsumer consumer, final Persiste String refName = persistenceContext.name(); if (refName.length() == 0) { - /** + /* * Was @PersistenceContext used at a class level without specifying the 'name' attribute? */ if (member == null) { @@ -4726,14 +4754,14 @@ private void buildPersistenceContext(final JndiConsumer consumer, final Persiste if (EntityManagerFactory.class.isAssignableFrom(type)) { failIfCdiProducer(member, "EntityManager"); - /** + /* * Was @PersistenceContext mistakenly used when @PersistenceUnit should have been used? */ fail(consumer.getJndiConsumerName(), "persistenceContextAnnotation.onEntityManagerFactory", persistenceContextRef.getName()); } else if (!EntityManager.class.isAssignableFrom(type)) { failIfCdiProducer(member, "EntityManager"); - /** + /* * Was @PersistenceContext mistakenly used for something that isn't an EntityManager? */ fail(consumer.getJndiConsumerName(), "persistenceContextAnnotation.onNonEntityManager", persistenceContextRef.getName()); @@ -5545,6 +5573,9 @@ private static void addRestClassesToScannedClasses(final WebModule webModule, fi clazz = classLoader.loadClass(className); classes.add(clazz); } catch (final ClassNotFoundException e) { + logger.debug("Could not load REST class {1} for web module {2} / {3}", + className, webModule.getJarLocation(), webModule.getFile().getName()); + throw new OpenEJBException("Unable to load REST class: " + className, e); } } diff --git a/container/openejb-core/src/main/resources/org/apache/openejb/config/rules/Messages.properties b/container/openejb-core/src/main/resources/org/apache/openejb/config/rules/Messages.properties index 6d81819043f..371549a9068 100644 --- a/container/openejb-core/src/main/resources/org/apache/openejb/config/rules/Messages.properties +++ b/container/openejb-core/src/main/resources/org/apache/openejb/config/rules/Messages.properties @@ -301,16 +301,16 @@ 3.asynchronous.badExceptionType = asynchronous method {0} in class {1} should not throw ApplicationException "{2}" while its return type is void. # warn("Asynchronous", "asynchronous.methodignored", beanClass.getName(), methodName); -1.asynchronous.methodignored = non-public method {1} in class {0} is ignored, although the class is annoated with @Asynchronous -2.asynchronous.methodignored = non-public method {1} in class {0} is ignored, although the class is annoated with @Asynchronous -3.asynchronous.methodignored = non-public method {1} in class {0} is ignored, although the class is annoated with @Asynchronous +1.asynchronous.methodignored = non-public method {1} in class {0} is ignored, although the class is annotated with @Asynchronous +2.asynchronous.methodignored = non-public method {1} in class {0} is ignored, although the class is annotated with @Asynchronous +3.asynchronous.methodignored = non-public method {1} in class {0} is ignored, although the class is annotated with @Asynchronous # AnnotationDeployer.java # warn("client.missingMainClass", className) # fail("client.missingMainClass", className) 1.client.missingMainClass = Missing Main-Class 2.client.missingMainClass = Missing Main-Class: {0} -3.client.missingMainClass = The Main-Class {0} specified in the MANIFEST.MF file does not exist in the jar. +3.client.missingMainClass = The Main-Class {0} specified in the MANIFEST.MF file does not exist in the jar {1}. # fail(ejbName, "xml.localRemote.conflict", interfce); 1.xml.localRemote.conflict = Interface illegally declared as both and . diff --git a/container/openejb-core/src/main/resources/org/apache/openejb/config/rules/Messages_hi.properties b/container/openejb-core/src/main/resources/org/apache/openejb/config/rules/Messages_hi.properties index 637751a7393..dc9c0a901e9 100644 --- a/container/openejb-core/src/main/resources/org/apache/openejb/config/rules/Messages_hi.properties +++ b/container/openejb-core/src/main/resources/org/apache/openejb/config/rules/Messages_hi.properties @@ -295,16 +295,16 @@ 3.asynchronous.badExceptionType = asynchronous method {0} in class {1} should not throw ApplicationException "{2}" while its return type is void. # warn("Asynchronous", "asynchronous.methodignored", beanClass.getName(), methodName); -1.asynchronous.methodignored = non-public method {1} in class {0} is ignored, although the class is annoated with @Asynchronous -2.asynchronous.methodignored = non-public method {1} in class {0} is ignored, although the class is annoated with @Asynchronous -3.asynchronous.methodignored = non-public method {1} in class {0} is ignored, although the class is annoated with @Asynchronous +1.asynchronous.methodignored = non-public method {1} in class {0} is ignored, although the class is annotated with @Asynchronous +2.asynchronous.methodignored = non-public method {1} in class {0} is ignored, although the class is annotated with @Asynchronous +3.asynchronous.methodignored = non-public method {1} in class {0} is ignored, although the class is annotated with @Asynchronous # AnnotationDeployer.java # warn("client.missingMainClass", className) # fail("client.missingMainClass", className) 1.client.missingMainClass = Missing Main-Class 2.client.missingMainClass = Missing Main-Class: {0} -3.client.missingMainClass = The Main-Class {0} specified in the MANIFEST.MF file does not exist in the jar. +3.client.missingMainClass = The Main-Class {0} specified in the MANIFEST.MF file does not exist in the jar {1}. # fail(ejbName, "xml.localRemote.conflict", interfce); 1.xml.localRemote.conflict = Interface illegally declared as both and .