We were using Pax Logging 1.6.1 for a long time (yes, I know it's old). We 
are now upgrading all of our infrastructure. We tried using Pax Logging 
1.10.2. After much debugging, I finally figured out why our logging isn't 
working the same way as before.

Someone added generics to Pax Logging in December 2015 in this commit: 
https://github.com/ops4j/org.ops4j.pax.logging/commit/57e0580e0ad290e96f9c4ff64d3d3682d8dedf6c#diff-abdd339630db78965e0e1db82369e4ef


In the original code, the m_loggers static variable for all LogFactory 
types (Commons Logging, SLF4J, Log4J, etc.) was initialized without 
generics as:
m_loggers = new WeakHashMap();


In the new code, this became:
m_loggers = new WeakHashMap<String, JclLogger>(); // Or <String, 
Slf4jLogger>, or <String, Logger>, etc., depending on type.

However, the original code was using m_loggers with the logger as the key 
and the name as the value, which means *the generics should have been*:
m_loggers = new WeakHashMap<JclLogger, String>(); // Or <Slf4jLogger, 
String>, or <Logger, String>, etc., depending on type.


The original code from 
pax-logging-api/src/main/java/org/apache/commons/logging/LogFactory.java 
is: 
<https://github.com/ops4j/org.ops4j.pax.logging/commit/57e0580e0ad290e96f9c4ff64d3d3682d8dedf6c?diff=split#diff-abdd339630db78965e0e1db82369e4ef>
 
    public Log getInstance(String name)
        throws LogConfigurationException
    {
        PaxLogger logger;
        if (m_paxLogging == null)
        {
            logger = FallbackLogFactory.createFallbackLog(null, name);
        }
        else
        {
            logger = m_paxLogging.getLogger(name, JclLogger.JCL_FQCN);
        }
        JclLogger jclLogger = new JclLogger(logger);
        synchronized (m_loggers) {
            m_loggers.put(jclLogger, name); // THIS LINE GOT CHANGED WHEN 
YOU ADDED GENERICS. KEY/VALUE GOT SWAPPED.
        }
        return jclLogger;
    }


After generics were added, the indicated line became:

            m_loggers.put(name, jclLogger); // THIS LINE GOT CHANGED WHEN 
YOU ADDED GENERICS.


Even in the old code, even if the same name was passed to getInstance 
twice, each one resulted in an independent JclLogger. But, *both* JclLogger 
instances were stored in m_loggers (because the *key* was the logger 
itself, and the name was the value), and *both* (or *all*, if the same name 
was used more than twice) got the proper Pax Logging configuration once the 
Pax Logging API and Service got started (the DefaultServiceLog, or whatever 
came out of the FallbackLogFactory, got replaced with a TrackingLogger, and 
then the logging properties from org.ops4j.pax.logging.cfg were respected).

With the new code, if you pass the same name to getInstance twice, each one 
still gets an independent JclLogger. But, when the call to m_loggers.put is 
made with a name that already has a JclLogger, the old JclLogger is removed 
from m_loggers, and m_loggers.get(name) only returns the new JclLogger. *When 
Pax Logging API and Service get started, only the most recent JclLogger for 
the name gets its DefaultServiceLog replaced by a TrackingLogger, and the 
other JclLogger instances for that name still use a DefaultServiceLog, 
because those JclLogger instances aren't stored in m_loggers anymore.* 
Then, when an attempt is made to log to the JclLogger that still uses 
DefaultServiceLog, the logging properties from Pax Logging in 
org.ops4j.pax.logging.cfg are ignored.

This happens for all loggers (Log4J, SLF4J, etc.), not just JclLogger.

We have Pax Logging API and Pax Logging Log4J2 1.10.2 jars in 
/var/payara5/glassfish/modules/autostart (which correlates to where we 
always had the old Pax Logging 1.6.1 jars in Glassfish 3.1.2.2--
/var/glassfish/glassfish/modules/autostart). When I use the "autodeploy" 
directory in my Glassfish domain to deploy a new war after the Glassfish 
domain is already up and running with Pax Logging started, all of the 
logging works correctly, because it never sees a DefaultServiceLog at all 
(it gets TrackingLogger immediately). If I stop the domain and restart it 
with a war already deployed, the war starts up with DefaultServiceLog instances 
(the war starts up before Pax Logging starts [war starts creating logger 
instances before the Activator for Pax Logging API is called])), and not 
all instances get changed to TrackingLogger, as described above. Thus, the 
logging is all messed up. If I "touch" the war (to force Glassfish to 
redeploy while Glassfish is running), then it gets the proper logging 
configuration, because Pax is started by now.

======================
*Based on the observed behavior, I regard this as a bug in Pax Logging. I 
should not have to redeploy my wars every time I restart my domain, just so 
that logging is picked up correctly.* There is no Jira ticket associated 
with the commit to "add generics". Thus, it is not clear that this was an 
intentional change to the behavior of Pax Logging. I'm surprised no one 
complained about it before.

Can you look at this and tell me if this is intentional, or if there is any 
other way to deal with it besides redeploy my wars every time we restart 
the Glassfish domain?

Thank you,
Monica

-- 
-- 
------------------
OPS4J - http://www.ops4j.org - [email protected]

--- 
You received this message because you are subscribed to the Google Groups 
"OPS4J" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/ops4j/952b7207-cd2b-4229-af4a-f60c934d2c1f%40googlegroups.com.

Reply via email to