0
votes

I am creating custom logging functionalities class that internally uses the LOG4j. those classes that wants to used logging functionalities,it pass the name of class.i want to know how i am able to restrict object creation without passing the class-name to it.i tried but i am not sure that Is it a correct way i did?


public class LoggerObject 
{
    private Logger logger;
    private static LoggerObject loggerobj;
    private ConstantDataManager constantdatamanger;

    //Default Log4J_FILE Path
    private LoggerObject(String className)
    {
      try
      {
        DOMConfigurator.configure(this.getClass().getClassLoader().getResource(constantdatamanger.LOG4J_FILE));
        logger =Logger.getLogger(className);
       }
      catch(Exception ex)
      {
          System.out.println("DOMConfigurator could not find file"+ex.getMessage());
      }
    }

     public static LoggerObject getLogger(String className)
        {
            if (loggerobj==null)
            {
             loggerobj = new LoggerObject(className);
            }
             return loggerobj;
        }


    public void info(Object message)
    {
        logger.info(message);
    }

    public void info(Object message, Throwable t) {
        logger.info(message, t);
    }

    public void error(Object message) {
         logger.error(message);
    }

    public void error(Object message, Throwable t) {
       logger.error(message,t);
    }

    public void debug(Object message) {
       logger.debug(message);
    }

    public void debug(Object message, Throwable t) {
        logger.debug(message,t);
    }

    public void warn(Object message) {
       logger.warn(message);
    }

    public void warn(Object message, Throwable t) {
       logger.warn(message,t);
    }

    public void fatal(Object message) {
       logger.fatal(message);
    }

    public void fatal(Object message, Throwable t) {
        logger.fatal(message,t);
    }

Thanks

4
Restrict how? Also implementing the slf4j API instead might make your code more portable.Thorbjørn Ravn Andersen

4 Answers

0
votes

LoggerObj is static and therefore only ever exists at the class level. After the first call to getLogger the variable is initialised and will continue to return the same object to other clients.

It looks like you want to create a factory for loggers but instead created a singleton?

0
votes

Why don't you just use Log logger = LogFactory.getLog(className);?

If you want to add more data to the logs automatically, you might use your LoggerObject but maybe you should pass the class instead of the class name, like this

class LoggerObject<T> {
 private LoggerObject(Class<T> clazz){
  ...
 }
}

If you want to restrict which classes are passed, you can use class LoggerObject<T extends SomeBaseClass>.

Edit:
You should be aware of this:

private static LoggerObject loggerobj;    

public static LoggerObject getLogger(String className)
{
  if (loggerobj==null)
  {
    loggerobj = new LoggerObject(className);
  }
  return loggerobj;
}

This will return the correct logger for the first call, then the passed className is ignored.

0
votes

The main approach to divide infrastructure logic to separate entity is testability.

Using constructor (or setter) injection instead of creating objects in the object you can easily replace this dependency with mocks. But I do not think that you testing based on logger is the best choice.

Second approach is code portability, but as @Thorbjørn Ravn Andersen already mentioned slf4j will be better for this task.

0
votes

I'm not entirely sure what you are trying to achieve, in any case this seems wrong:

public static LoggerObject getLogger(String className)
    {
        if (loggerobj==null)
        {
         loggerobj = new LoggerObject(className);
        }
         return loggerobj;
    }

You implemented a singleton pattern, however you are storing the className ("foo") passed in the first getLogger call. This means all subsequent calls to getLoggger("bar") will return a LoggerObject with className "foo". If you want one logger to rule them all, then its name should probably be an application constant or configurable property, not the first name that happens to be passed by a logging client.

The regular Log4J idiom is:

private static final Logger LOG = Logger.getLogger(abc.xyz.MyLoggingClient.class);

This creates a logger with the argument's fully qualified classname as its name. In log4j.properties you would have stuff like:

log4j.logger.abc.xyz.MyLoggingClient=WARN

Please explain what you would exactly like to achieve that you cannot do with plain Log4j.