2

I want to extend the java.util.logging.Logger class.

I have the following code. I am "forcing an error" in our app and the class I created is not being called.

Here is the error I am generating on purpose but it doesn't go in the code I wrote:

//Generate error to test the logger
String[] myStringArray = new String[3];
String test;
test = myStringArray[5];    

I also tried this but it still doesn't go in my code even if I have the same function definition:

logger.log(Level.FINE, "test my logger");

Here is my logger extension. Is it possible for this to get triggered when an unhandled exception is "raised".

import java.util.logging.Level;
import java.util.logging.LogRecord;

public class MyLogger extends java.util.logging.Logger
{

    public MyLogger(String name, String resourceBundleName)
    {
        super(name, resourceBundleName);
        runMyLog();
    }


    public void log(Level level, String msg) {
        runMyLog();
    }   

    public void error(String msg)
    {
        super.log(Level.SEVERE, msg);
        runMyLog();
    }

    public void log(LogRecord record)
    {
        super.log(Level.SEVERE, record.getMessage());
        runMyLog();
    }

    public void severe(String msg) {
        log(Level.SEVERE, msg);
        runMyLog();
    }

    public void runMyLog(){
        String str = "lll";

        str="fdsafasdfdasfasd";
    }
}
E-Riz
  • 31,431
  • 9
  • 97
  • 134
SomeGuy
  • 21
  • 3
  • Where are you creating an instance of your logger class? – E-Riz Jun 22 '16 at 19:41
  • It's created for each class we have. Here is a sample `code` public class AuthModel implements Serializable { ... private static final Logger logger = Logger.getLogger(AuthModel.class.getName()); ... public String part1() throws IOException { logger.log(Level.FINE, "in part1"); //---my extends class is not getting called `code` – SomeGuy Jun 22 '16 at 19:43
  • How do you expect getLogger() to know about your subclass and return and instance of it? – E-Riz Jun 22 '16 at 19:47
  • Sorry, I do Shift+Enter but the output doesn't seem to take effect ! Even tried to wrap the code in the mini-markdown but it doesn't seem to work..sorry new to this site – SomeGuy Jun 22 '16 at 19:47
  • because I extend it ? right ? – SomeGuy Jun 22 '16 at 19:48
  • You can edit the question to add more code. Don't add it in the comments. – E-Riz Jun 22 '16 at 19:48
  • thanks. From what I've read I can extend the logger class by simply using: public class MyLogger extends java.util.logging.Logger ... Is there more I have to do ? – SomeGuy Jun 22 '16 at 19:49
  • 1
    Defining a subclass and obtaining instances of that subclass are two different things. Honestly, that's a very basic Java and Object Oriented programming topic, not specific to logging at all. – E-Riz Jun 22 '16 at 19:51
  • I see may examples like this i'm not sure I understand. [link]http://stackoverflow.com/questions/28451374/extend-java-logging-for-another-log-level[link] – SomeGuy Jun 22 '16 at 19:54
  • It's not generally a good idea to extend `Logger`, especially if you don't quite understand OOP. See the "subclassing info" note http://docs.oracle.com/javase/6/docs/api/java/util/logging/Logger.html – leonbloy Jun 22 '16 at 19:58

1 Answers1

0

As @leonbloy and @E-Riz pointed out, per the documentation:

Therefore, any subclasses of Logger (unless they are implemented in conjunction with a new LogManager class) should take care to obtain a Logger instance from the LogManager class and should delegate operations such as "isLoggable" and "log(LogRecord)" to that instance. Note that in order to intercept all logging output, subclasses need only override the log(LogRecord) method. All the other logging methods are implemented as calls on this log(LogRecord) method.

So here would be an example that must be run with -Djava.util.logging.manager=bad.idea.OdiousLogManager so the JVM uses the new LogManager:

package bad.idea;

import java.awt.Toolkit;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

public class OdiousLogManager extends LogManager {

    @Override
    public synchronized Logger getLogger(String name) {
        Logger l = super.getLogger(name);
        if (l == null) {
            l = new AbhorentLogger(name, null);
            super.addLogger(l);
        }
        return l;
    }


    private static class AbhorentLogger extends Logger {

        AbhorentLogger(String name, String resourceBundleName) {
            super(name, resourceBundleName);
        }

        @Override
        public void log(LogRecord record) {
            super.log(record);
            mightyCatHearMeRoar(record);
        }

        private void mightyCatHearMeRoar(LogRecord record) {
            if (super.isLoggable(record.getLevel())) {
                Toolkit.getDefaultToolkit().beep();
            }
        }
    }


    //...
    private static final Logger logger = Logger.getLogger("godaweful");
    public static void main(String[] args) {
        logger.severe(logger.getClass().getName());
    }
}

If you only want to listen to events then you should simply implement a custom handler and avoid extending logger.

jmehrens
  • 10,580
  • 1
  • 38
  • 47
  • Thanks was missing the @override. – SomeGuy Jun 27 '16 at 12:06
  • This appears to be the only designed way to subclass the JUL implementation, and its a bit cumbersome. The main disadvantage of that is that it doesn't allow you to do what I need, which is to extend the `Logger` API with additional methods (for example, some helper methods). – Guss Oct 18 '16 at 13:00
  • @Guss If you want to tie your application to a LogManager and Logger subclass you can always cast the result of getLogger. `private static final AbhorentLogger logger = (AbhorentLogger) Logger.getLogger("logger.name");` – jmehrens Oct 18 '16 at 13:54
  • Yea, down-casting is the last refuge if people who are locked into a bad API... :-( My rule of thumb - if you're doing a down-cast, you're using a bad API. – Guss Oct 18 '16 at 14:01