5

Ok, the case is simple. I need to be able to enable/disable logging for a JDK class (HttpURLConnection) programmatically.

public class HttpLoggingTest {

    /**
      Just a dummy to get some action from HttpURLConnection
    */
    private static void getSomething(String urlStr) throws MalformedURLException, IOException {
        System.out.println("----- " + urlStr);
        HttpURLConnection conn = (HttpURLConnection) new URL("http://www.google.com").openConnection();

        for (Entry<String, List<String>> header : conn.getHeaderFields().entrySet()) {
            System.out.println(header.getKey() + "=" + header.getValue());
        }
        conn.disconnect();

    }

    public static void main(String[] args) throws MalformedURLException, IOException {

        // HERE : Enable JDK logging for class
        // sun.net.www.protocol.http.HttpURLConnection
        getSomething("http://www.goodle.com");

        // HERE: Disable JDK logging for class
        // sun.net.www.protocol.http.HttpURLConnection
        getSomething("http://www.microsoft.com");           
    }        
}

In other words: before the first URL call the logging must be enabled and then disabled before the next call.

That is the challenge !
I'm unable to figure out how to do it.

Must work with Java 7.

Note:

I can do it by using configuration file, logging.properties :

sun.net.www.protocol.http.HttpURLConnection.level = ALL

but I want to have a programmatic solution.

UPDATE

Here's code that works in Java 6 but not in Java 7:

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Map.Entry;
import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;    

public class HttpLoggingTest {

    /**
      Just a dummy to get some action from HttpURLConnection
    */
    private static void getSomething(String urlStr) throws MalformedURLException, IOException {
        System.out.println("----- " + urlStr);
        HttpURLConnection conn = (HttpURLConnection) new URL("http://www.google.com").openConnection();

        for (Entry<String, List<String>> header : conn.getHeaderFields().entrySet()) {
            System.out.println(header.getKey() + "=" + header.getValue());
        }
        conn.disconnect();            
    }

    private static void enableConsoleHandler() {
        //get the top Logger
        Logger topLogger = java.util.logging.Logger.getLogger("");

        // Handler for console (reuse it if it already exists)
        Handler consoleHandler = null;
        //see if there is already a console handler
        for (Handler handler : topLogger.getHandlers()) {
            if (handler instanceof ConsoleHandler) {
                //found the console handler
                consoleHandler = handler;
                break;
            }
        }

        if (consoleHandler == null) {
            //there was no console handler found, create a new one
            consoleHandler = new ConsoleHandler();
            topLogger.addHandler(consoleHandler);
        }
        consoleHandler.setLevel(Level.ALL);
    }

    public static void main(String[] args) throws MalformedURLException, IOException {

        enableConsoleHandler();

        final Logger httpLogger = Logger.getLogger("sun.net.www.protocol.http.HttpURLConnection");


        // Enable JDK logging for class
        //sun.net.www.protocol.http.HttpURLConnection
        httpLogger.setLevel(java.util.logging.Level.FINE);
        getSomething("http://www.goodle.com");

        // Disable JDK logging for class
        // sun.net.www.protocol.http.HttpURLConnection
        httpLogger.setLevel(java.util.logging.Level.INFO);
        getSomething("http://www.microsoft.com");           
    }        
}

UPDATE2

In order to make sure that a solution only enables output from our target class (and not all sorts of other JDK internal classes) I've created this minimal JAXB example. Here JAXB is simply an example of 'something else', it could have been any other part of the JDK that also use PlatformLogger.

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * Minimal dummy JAXB example. Only purpose is to provoke
 * some JAXB action. Non-prod quality!
 */
@XmlRootElement(name = "book")
public class Celebrity {

    @XmlElement
    public String getFirstName() {
        return "Marilyn";
    }

    @XmlElement
    public String getLastName() {
        return "Monroe";
    }

    public void printXML() {
        JAXBContext context;
        try {
            context = JAXBContext.newInstance(Celebrity.class);
            Marshaller m = context.createMarshaller();
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            m.marshal(this, System.out);
        } catch (JAXBException ex) {
        }
    }
}

Instantiate an instance of the Celebrity class and call printXML(). Put that into getSomething() method. This must not generate JAXB internal logging output ... or else you've enabled logging for more than you thought.

7
  • Note: the example can be copy/pasted and executes as-is. Commented Jan 9, 2014 at 21:08
  • What are you trying to log? Only the headers? Commented Jan 9, 2014 at 21:12
  • @SotiriosDelimanolis No the display of the headers is just to provoke some action in the example. I don't decide what gets logged. That's up to the sun.net.www.protocol.http.HttpURLConnection class ... and I'm happy with that. But how do I enable it programmatically ? Commented Jan 9, 2014 at 21:14
  • That code doesn't compile for me in Java 7. Entry is unresolvable. Supposed to be Map.Entry I assume. Commented Jan 9, 2014 at 21:55
  • @mttdbrd. Must be your imports that are wrong. I've included them now in the example above. Commented Jan 9, 2014 at 22:04

2 Answers 2

2

Stumbled over PlatformLoggingMXBean the other day. I'll need to try something like:

PlatformLoggingMXBean platformLoggingMXBean = 
    ManagementFactory.getPlatformMXBean(PlatformLoggingMXBean.class);
platformLoggingMXBean.setLoggerLevel(
    "sun.net.www.protocol.http.HttpURLConnection", "FINE");

and see it it works.

Sign up to request clarification or add additional context in comments.

Comments

1

Try:

java.util.logging.Logger logger = 
        java.util.logging.Logger.getLogger(
            "sun.net.www.protocol.http.HttpURLConnection");
logger.setLevel(java.util.logging.Level.FINE);

3 Comments

Nope. Sorry mate. If only it was that simple. See updated question above.
Mate, gave you a downvote first but removed it again because you are trying to be helpful (appreciated!) and of course this is the right answer ... if it wasn't because this is Java 7 and the class in question is internal JDK. :-(
this doesn't work on Java 8 either. On Java 8 this worked sun.util.logging.PlatformLogger .getLogger("sun.net.www.protocol.http.HttpURLConnection") .setLevel(PlatformLogger.Level.ALL); so I reckon this'll work on Java 7 too

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.