How to initialize registrars correctly?

I have the following problem: I want to use java.util.logging.Logger . No, I found different resources 1 , 2 , 3 , how you can change the behavior of the registrar.

Especially in question 2 a (in my opinion) a good structure is given for initializing registrars according to the class name. It also allows you to modify verbosity at the package level for debugging if necessary.

After a little digging into the problem, I found out that the global registrar and the "empty" registrar (with the name "" ) do not match. See also an example below. I just created a registrar foo.Bar , which is tied to an empty registrar instead of a registrar named foo . Only if I first create a logger bar , the bar.Baz log bar.Baz bound to it correctly.

This makes the approach in this matter mostly useless, since it cannot be assumed that parent registrars should be created earlier. As far as I know, you need to parse the class name and create registrars as needed.

I will correct that I need to add some static {...} code to initialize the registrars in a recursive way before my own log can be initialized? Does this have any negative effect if several classes call the Logger.getLogger(String) method for packet loggers (resulting in the total number of calls in general, for example, both bar.Baz and bar.FooBaz receiving the bar log)?

 import java.util.Enumeration; import java.util.logging.LogManager; import java.util.logging.Logger; public class TestLogger { public static void main(String[] args) { // Create the logger directly Logger.getLogger("foo.Bar"); // Create the logger objects step-by-step Logger.getLogger("bar"); Logger.getLogger("bar.Baz"); // Put the available loggers to output Enumeration<String> e = LogManager.getLogManager().getLoggerNames(); while(e.hasMoreElements()) { String s = e.nextElement(); Logger l = Logger.getLogger(s); String p = (l.getParent() == null ? "none" : "'" + l.getParent().getName() + "'"); System.out.println("'" + s + "': " + p); } } } 

Program exit

 'bar': '' 'global': '' 'foo.bar': '' 'bar.baz': 'bar' '': none 
+6
source share
1 answer

One negative effect of having Logger.getLogger(String) in each class is that you cannot mock it (or pass in a special log) for tests.

Example: say you need to test the following C class:

 package ab; class C { private Logger logger; private int capacity; private int size; C(int capacity) { this.logger = Logger.getLogger("abC"); this.capacity = capacity; size = 0; } void add(int item) { if (size >= capacity) { logger.log("You already reached the capacity: " + capacity); } //... } } 

It is a requirement to add logs if capacity is reached. Now you need to test it. It is very difficult and hacked to do a test that checks this:

 public void testCapacityReachedLogs() { C c = new C(2); c.add(1); c.add(2); // verify that c logged the exact string: "You already reached the capacity: 2" } 

However, if you have:

 package ab; class D { private Logger logger; private int capacity; private int size; D(Logger logger, int capacity) { this.logger = logger; this.capacity = capacity; size = 0; } void add(int item) { if (size >= capacity) { logger.log("You already reached the capacity: " + capacity); } //... } } 

Now you can mock Logger:

 public void testCapacityReachedLogs() { Logger logger = getMock(Logger.class); D d = new D(logger, 2); d.add(1); d.add(2); verify(logger).log("You already reached the capacity: 2"); } 

Please note that the “layout” associated with the code does not necessarily follow the syntax of the framework, it is simple, for example.

+1
source

All Articles