is it possible to determine the class of an implementing class in a static context. Given i want to create a logger in the superclass which logs its messages under the class name of the implementing classes.
Currently i'm trying to use this approach:
public abstract class GenericDao<T, ID extends Serializable>
{
protected static Logger logger = Logger.getLogger(new Object() { }.getClass().getEnclosingClass());
...
}
But i still get the superclass. Is there any way to do this or should i give up and include the class in the actual logging method when i have access to "this".
Static variables and methods always belong to the declaring class, GenericDao in this case. If you create a new subclass SpecificDao then it is not accessing a new copy of logger if it accesses it, it is accessing the exact same logger as is in GenericDao.
You will need to create the Logger as a non-static member and have one per object (potentially very inefficient) , or declare the logger in each class.
What should work to give you what you want though is if you have an abstract method getLogger() in GenericDao and no Logger at all..
Whenever it wants to log GenericDao calls getLogger().log
The implementing classes then define their own private static Logger logger. They override the getLogger() abstract method and return the static one from that.
Related
I am having a util class as below, which has a static method to do rest invocation which is calling from many beans in the spring boot application. I only have logger as a instance variable in the Util class.
public class Util{
private static final Logger LOGGER = LoggerFactory.getLogger(Util.class);
public static String post(RestTemplate restTemplate){
restTemplate.exchange();
}
}
I would like to get clarify below points.
Even I dont have a instance variable relate to RestTemplate in my util class, I notice with in RestTemplate class it has inner classes and maintain instance variables with in it. Would that be a issue when multiple users concurrently access the post method.
Is it ok to use org.slf4j.Logger as a instance variable here? Do I need to pass LOGGER as a method local parameter as well?
Part 1
Every time a third-party API is called via RestTemplate it will create new Httpconnection and will close it once it is done. You can create RestTemplate's own connection pool using HttpComponentsClientHttpRequestFactory like so:
new org.springframework.web.client.RestTemplate(new HttpComponentsClientHttpRequestFactory())
So it should not create any problems if the connections are new with each method call. Check this answer of mine here -- How does resttemplate.exchange() execute on a different thread?
Part 2
Having a static variables in a util class with static methods only is fine. Having said that, Adding --
private static final Logger LOGGER = LoggerFactory.getLogger(Util.class);
-- in each of the classes seems to more of a boilerplate code which can be avoided if you use Lombok's #Slf4j annotation like so --
#Slf4j
public class LogExample {
}
This will generate somethig like this:
public class LogExample {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
}
Consider and example as below:
public class LoggerTestClass {
private static final Logger LOGGER = Logger.getLogger(LoggerTestClass.class);
}
In above example parameter passed to getLogger method is hard coded i.e LoggerTestClass.class
Now every time I change the class name I have to change the getLogger method's parameter.
Any other way which will fetch the class name automatically, for example for non static variable we can add this.getClass()
You can use Lombok to achive it in a clean fashion. All you need to do is to put #Log on top of your class and it will give you a log object to work with.
Read more here
Bro,For the question,first of all,we need make clear some concept.
In java,if a identifier is a member of a class,and decorated by 'static' keyword,it's value is Decided in the compile phase.
If the 'final' keyword is added,the identifier is constant,it's value must have a initial value on it is declared.and the value can't be change in the java runtime.
And the interesting thing is, the static constent is only declared inside the class,it can be called 'Classname' + '.' ,but has no connection to the class context.if there's no context ,the identifier con't become dynamic.
I think if let the identifier become dynamic ,there are only two ways:
let the identifier become a variable.remove the 'final' key word.the code look like this:
class Test {
private static Logger LOGGER;
public Test() {
LOGGER = Logger.getLogger(getClass().getSimpleName());
}
}
The 'private' keyword is sufficient if you don't want other classes to access it.
Try the java dynamic proxy. it can change the class in java runtime.
Code happy ~
Welcome to talk with me~
Can you use java 9+? Then solution is pretty simple:
private static final Logger LOGGER = Logger.getLogger(MethodHandles.lookup().lookupClass());
As MethodHandles.lookup() creates lookup using caller class. (via Reflection.getCallerClass() but Reflection is internal API, so you need that additional method handle lookup step)
I understand that java.lang.SecurityManager is used to check and constrain class access or file access based on a specific scenario.
I need to identify the caller for Log4J Helper class which needs to return the Logger instance based on Class which calls the Helper class.
There are two ways to do this.
Using Threads
public static Logger getLogger() {
final Throwable thread = new Throwable();
final StackTraceElement callerMethod = thread .getStackTrace()[1];
final Logger logger = Logger.getLogger(callerMethod .getClassName());
return logger;
}
This is a performance bottleneck since it involves get the current stacktrace for each call to getLogger
Second Approach
Logging helper to extend java.lang.SecurityManager in which case i can use
getClassContext()[2].getName();
to get the absolute class name for instantiating the Logger.
The LoggingHelper extending the SecurityManager doesn't seem to be a good design principle considering its usage.
Would there any be any reason i can extend SecurityManager to a Logging Utility or is there a better approach?
Note : The application will be running in app server instance.
If you're using Java EE 6 you could use CDI to inject your logger.
public class LoggerProducer {
#Produces
public Log createLogger(final InjectionPoint injectionPoint) {
final String name = injectionPoint.getMember().getDeclaringClass().getName();
return Logger.getLogger(name);
}
}
I have this parent abstract class which defines an Apache logger static object. Something like this:
import org.apache.log4j.Logger;
public abstract class A {
private final static Logger logger;
(...)
}
I know this code is illegal because the logger object is not initialized. The problem is I don't want to initialize it with logger = Logger.getLogger(A.class); because I want each child class to initialize it with its own class object, that way I will know which class caused which errors.
But at the same time I want to include some of my logging methods on the base class A.
What would be the best practice for this? Should I initialize it with A.class, then reinstantiate it for each child class? Somehow that feels incorrect to me.
Initialize it with the actual class it's created in:
logger = Logger.getLogger(getClass()); //log4j way of creating loggers
To do this you'll need to remove static modifier from your logger declaration.
I prefer to keep it private and access it via a getter-method, but you can also make it protected and access directly from A subclasses.
You should not worry that many logger objects will be created, one logger per class instance: under the hood Logger contains a map of loggers, and every time you create a new logger - it's being cached. When you try to get logger for the same class the second time - it's just being retrieved from the inner map.
So, if you have 5 classes in your hierarchy - only 5 Logger objects will be created, no matter how many times you call getLogger(getClass()).
Should I initialize it with A.class, then reinstantiate it for each
child object?
You should reinstantiate it for each child class.
I have a class in which I see the following things:
this.logger.severe("");
this.logger.warning("");
this.logger.info("");
I do not understand several things:
How can we use a method that was not defined earlier? I mean, there are no "logger" methods defined in the class. I thought that these methods could be defined because the considered class is an extension of another class in which the "logger" is defined. But in the definition of the class there no "extends" statement (only "implements").
I can understand things like that: "objectName.methodName". But what is that "objectName.something1.something2"? "something1.something2" is name of a method? Can method names contain dots?
What exactly these "logger.*" do? I think they save information about the execution of the code. They kind of write report about what happened during the execution. But where I can find this information?
ADDED:
In the beginning of the file I have: import java.util.logging.Logger;
And then in the class I have: private Logger logger = Logger.getLogger("a.b.c.d");
So, logger is an object of the class Logger (but I do not understand why they could not instantiate the class in a usual way using "new Logger()). I also do not understand what exactly logger.severe("") do.
The logger doesn't make anything special. It's all just Java code.
public class SomeClass {
private Logger logger = LogFactory.getLogger(SomeClass.class);
public void doSomething() {
this.logger.debug("foo");
}
}
The this.logger just points to the instance variable named logger of the current instance (this). The this. prefix is by the way superflous in this example. One could also just do logger.debug("foo") here.
If it is not declared in the SomeClass itself, then it's likely been declared in the extending class. Check the class which is declared in extends.
As to your objectName.something1.something2 doubt, have you already looked how System.out.println() works? The System.out returns a PrintStream object which in turn has a println() method. Thus, if objectName.something returns a fullworthy Object with methods, then you can just continue chaining method calls.
Basically,
objectName.something1.something2;
can be translated as
SomeObject someObject = objectName.something1;
someObject.something2;
But if you don't need someObject anywhere else in the code, then it can just be shortened as in your example.
Update: as per your update:
So, logger is an object of the class Logger (but I do not understand why they could not instantiate the class in a usual way using "new Logger()). I also do not understand what exactly logger.severe("") do.
Just read the javadoc of the class in question what it all does. As to why it can't be instantiated, it's because of the factory pattern.
Update 2: as per the another confusion:
I do not understand why they use "this". I mean, if I use just field name, will it not be, by default, the field of this object? I there any difference between "this.x" and "x"?
This way you can be more explicit about which one you'd like to access. If the method contains for example an argument or a local variable with the name logger, then this.logger would still refer to the instance variable.
public class SomeClass {
private Logger logger = LogFactory.getLogger(SomeClass.class);
public void doSomething(Logger logger) {
this.logger.debug("foo"); // Refers to the instance variable.
logger.debug("foo"); // Refers to the method argument.
}
public void doSomethingElse() {
Logger logger = LogFactory.getLogger(SomeClass.class);
this.logger.debug("foo"); // Refers to the instance variable.
logger.debug("foo"); // Refers to the method local variable.
}
}
The logger usually refers to the usage of a class in log4j.
The logger is a member object whose function e.g. severe is called.
The logger usually logs into a file (this can be configured through log4j.xml or some other config file or during the program start).
Edit: Changed the log4j link.
The 'logger' will be another object, not a method. This logger class will have methods defined on it like public void severe(String message)
'something1' will be an object contained by 'objectName'. For example, Car.Engine.Cylinder.Fire(), it's considered bad practise to use a method to fire a car's cylinders like this, and you should do something more like Car.StartEngine() (see the law of demeter for more info)
The logger will keep a record of what's happened in your program, so if there's a crash or a bug later on, you can see what happened. Whether this is recorded to a text file, or to a database somewhere, will be down to the implementation of your logger.
logger is not a method but a class variable which seems to be an object that exposes the methods "severe", "warning" and "info".
Check your class for something like "someClass logger = new someClass();"
The java.util.Logger class is the main access point to the Java logging API. Here is how you create a logger:
Logger logger = Logger.getLogger("myLogger");
The string passed as parameter to the getLogger() factory method is the name of the Logger to create. You can choose the name freely, but the name implies where the Logger is located in the Logger hierarchy. Every . (dot) in the name is interpreted as a branch in the hierarchy.