Logging static methods if lombok.log.fieldIsStatic is set to false - java

I joined a new project which uses lombok #Slf4j for logging but has the following configuration:
lombok.log.fieldIsStatic=false
This prevents me from using Lombok's logger in static methods. I didn't get an explanation on why it is configured like this, but I am not allowed to change it. Obviously I can do it the old fashion way for static methods, e.g.
private static final Logger LOG = LoggerFactory.getLogger(MyClass.class);
but I love the annotated approach. So my question is whether it is possible to have it both ways, i.e. use Lombok's logging approach for both static and non-static methods without changing the lombok.log.fieldIsStatic property value.
Thank you for your attention.

From the docs
Configuration files are hierarchical: Any configuration setting
applies to all source files in that directory, and all source files in
subdirectories, but configuration settings closer to the source file
take precedence.
So you could create a second Lombok config file which is exclusive to one module, or maybe even just one package, which overrides the property at the root level to reset it back to static.
Otherwise, no.
I didn't get an explanation on why it is configured like this, but I
am not allowed to change it
This sounds like a cultural issue. I am all for following an established precedent, but only if someone can and will justify why it was chosen.

Related

Initialising the logger in each and every class in java of sl4j

'
I am using sl4j for logging in my java classes although I have added the dependency too, my question is that if I have lots of java classes say a count of 50 classes in different packages, then for logging do I need to add the below statement in my every class, rite now suppose below code is for my main class is
final Logger LOG = LoggerFactory.getLogger(Main.class);
Is there any way through which I do not need to initialize the logger of sl4j in each and every class explicitly
It is always recommended to use the following code.
final Logger LOG = LoggerFactory.getLogger(Main.class);
It is required because, all the log statements are specific to specific classes and methods for log analysis. If we create a separate alternative to the above statement, then also we need to define in each class. Think of a situation, we have System.out.println statement which we write everywhere for analysis. Can we think of alternative to the above ? I don't think.
If your project is spring based, you can use AOP to log the messages.

Implementing logger for java application

I am trying to implement logger using apache commonn logging and log4j.xml file as configuration file .
So in the actual java code i am writing log as
I am using appache common logging
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
and i am logging information such as in . I am creating a instance of log for each class
private static Log logger = LogFactory.getLog( MyClass.class );
private static final String name ="SAM";
logger.info("name= "+name);
So now my question is does implementing logger like this create a performanace issue?
Is it necessary to check log like
if ( log.isInfoEnabled( ) )
{
log.info( "Info message" );
}
The confusion is mainly because in Apache common logging they have mentioned to do this and in log4j they have mentioned it is unnecessary.
Each time when we write log in the files?
-Sam
yes and no, logging always reduces your performance, but some functions are more expensive then others, e.g. getting the calling class/method-Name uses reflection and is very slow. But a normal logfuntion is not that expensive if you do not have an expensive statement in the calling logging function (this will be evaluated every time before the log-Level is checked. In this case you can use the .isLevelEnabledcheck to prevent the evaluation). Also logging to the console takes longer for the output than logging to a file. You will find more information about this by googling and in the FAQ/manual of log4j.
You do not have to check the Log-Level before logging. This is done within the log-function itself. Therefore are the different methods for every Level or the Level-Argument in the generic log-Method.
A big potential performance problem with logging is usually if you have something passed into the log method that is very expensive to convert to a string. That's why you have methods like isInfoEnabled(), so that the code can avoid creating the message string from the parameter (otherwise the check within the info() method is too late, the conversion is already done). If your objects passed into the log methods are strings or are not very involved then the is*Enabled() methods won't be that useful.
SLF4J is worth checking out. It doesn't depend on classloader tricks (which is a big part of why commons-logging is reviled), and it has a different way of creating log messages which delays when the message string gets created so that the enabled check can take place within the logging method.
There's a better way to do all of this. You can get really great performance without having to add the clutter of ifDebugEnabled, etc methods. Check out something like Logback (or SLF4J). Here's the great documentation about what kind of an API you want. Note that Log4J and Commons-Logging doesn't have an API like this. Use Parameterized Logging.

Should logger be private static or not

Should logger be declared static or not? Usually I've seen two types of declaration for a logger :
protected Log log = new Log4JLogger(aClass.class);
or
private static Log log = new Log4JLogger(aClass.class);
Which one should be used? what are the pro's and con's of both?
The advantage of the non-static form is that you can declare it in an (abstract) base class like follows without worrying that the right classname will be used:
protected Log log = new Log4JLogger(getClass());
However its disadvantage is obviously that a whole new logger instance will be created for every instance of the class. This may not per se be expensive, but it adds a significant overhead. If you'd like to avoid this, you'd like to use the static form instead. But its disadvantage is in turn that you have to declare it in every individual class and take care in every class that the right classname is been used during logger's construction because getClass() cannot be used in static context. However, in the average IDE you can create an autocomplete template for this. E.g. logger + ctrl+space.
On the other hand, if you obtain the logger by a factory which in turn may cache the already-instantiated loggers, then using the non-static form won't add that much overhead. Log4j for example has a LogManager for this purpose.
protected Log log = LogManager.getLogger(getClass());
I used to think that all loggers should be static; however, this article at wiki.apache.org brings up some important memory concerns, regarding classloader leaks. Declaring a logger as static prevents the declaring class (and associated classloaders) from being garbage collected in J2EE containers that use a shared classloader. This will result in PermGen errors if you redeploy your application enough times.
I don't really see any way to work around this classloader leak issue, other than declaring loggers as non-static.
The most important difference is how it affects your log files: in which category do logs go?
In your first choice, the logs of a subclass end up in the category of the superclass. That seem very counter-intuitive to me.
There is a variant of your first case:
protected Log log = new Log4JLogger(getClass());
In that case, your log category says which object the code that logged was working on.
In your second choice (private static), the log category is the class that contains the logging code. So normally the class that is doing the thing that is being logged.
I would strongly recommend that last option. It has these advantages, compared to the other solutions:
There is a direct relation between the log and the code. It is easy to find back where a log message came from.
If someone has to tune logging levels (which is done per category), it is usually because they are interested (or not) in some particular messages, written by a particular class. If the category is not the class that is writing the messages, it is harder to tune the levels.
You can log in static methods
Loggers only need to be initialized (or looked up) once per class, so at startup, instead of for every instance created.
It also has disadvantages:
It needs to be declared in every class where you log messages (no reuse of superclass loggers).
You need to take care to put the right classname when initializing the logger. (But good IDE's take care of that for you).
Use inversion of control and pass the logger into the constructor. If you create the logger inside the class you are going to have a devil of a time with your unit tests. You are writing unit tests aren't you?

How do I avoid unwanted log messages on java project?

On my java project, I have a bunch of strings externalized on a messages.properties file. On its respective Messages.java file I had the same number of public static String-typed attributes, so I could access those externalized texts.
Then, I implemented a method called getString, which receives the name of the constant as its argument and returns the wanted text. This way, there is no need to declare all the public static Strings-typed attributes inside the Messages.java file.
But after doing this my log became filled with "NLS unused message" messages.
Do you know if there's a way to prevent those warning messages to be logged?
Thanks in advance.
Your Messages class - it sounds like it extends org.eclipse.osgi.util.NLS.
If this is the case, it is designed to fill the requirements:
to provide compile time checking that a message exists.
to avoid the memory usage of a map containing both keys and values (this would be the case in a resource bundle approach).
good i18n support.
i.e. NLS populates the value of the Message.staticVariable with the value of the staticVariable found in messages.properties.
The warning logging provides information about a mismatch between the Messages.java and the messages.properties file.
Your getString() method sounds like it does not use any of the advantages of NLS, so as others have suggested, you may be better off using a ResourceBundle.
Messages sounds like a class you wrote, because I don't see it in my JDK 6 javadocs.
It sounds like you've tried to reinvent java.util.ResourceBundle. I'd recommend using that instead and ditching your class. It'll have the added advantage of handling I18N properly.
I don't see any value in hard-coding the public static message keys in the class. It's just another thing you'll have to maintain. If I understand what you're doing properly, I'd throw away your Messages and use ResourceBundle instead.
duffymo, as jamesh said, Messages is a class I wrote, and it extends org.eclipse.osgi.util.NLS. It has a private static attribute, and its type is... ResourceBundle!
jamesh, thanks for detailing the way NLS works.
Based on your answers I removed my Messages class from my project and added a ResourceBundle-typed attribute on the classes that need to use the externalized strings. Plus, I did it in a way that the lines accessing the externalized strings did not need to be changed.
The number of files on our project has been reduced, the code was kept as clean as before and there are no more log warnings.
Thank you, guys. You rock.

Correct approach to Properties

I am working in Java on a fairly large project. My question is about how to best structure the set of Properties for my application.
Approach 1: Have some static Properties object that's accessible by every class. (Disadvantages: then, some classes lose their generality should they be taken out of the context of the application; they also require explicit calls to some static object that is located in a different class and may in the future disappear; it just doesn't feel right, am I wrong?)
Approach 2: Have the Properties be instantiated by the main class and handed down to the other application classes. (Disadvantages: you end up passing a pointer to the Properties object to almost every class and it seems to become very redundant and cumbersome; I don't like it.)
Any suggestions?
I like using Spring dependency injection for many of the properties. You can treat your application like building blocks and inject the properties directly into the component that needs them. This preserves (encourages) encapsulation. Then, you assemble your components together and create the "main class".
A nice side effect of the dependency injection is that your code should be more easily testable.
Actually, approach 2 works really well.
I tried using a Singleton properties object on a recent project. Then, when it came time to add features, I need to revise the Singleton, and regretted having to locate every place where I used MySingleton.getInstance().
Approach 2 of passing a global information object through your various constructors is easier to control.
Using an explicit setter helps, too.
class MyConfig extends Properties {...}
class SomeClass {
MyConfig theConfig;
public void setConfi( MyConfig c ) {
theConfig= c;
}
...
}
It works well, and you'll be happy that you tightly controlled precisely which classes actually need configuration information.
If the properties are needed by a lot of classes, I would go for approach 1. Or perhaps a variant in which you use the Singleton design pattern instead of all static methods. This means that you don't have to keep passing some properties object around. On the other hand, if only a few classes need these properties, you might choose approach 2, for the reasons you mentioned. You might also want to ask yourself how likely it is that the classes you write are actually going to be reused and if so, how much of a problem it is to also reuse the properties object. If reuse is not likely, don't bother with it now and choose the solution that is the simplest for the current situation.
Sounds like you need a configuration manager component. It would be found via some sort of service locator, which could be as simple as ConfigurationManagerClass.instance(). This would encapsulate all that fun. Or you could use a dependency injection framework like Spring.
Much depends on how components find each other in your architecture. If your other components are being passed around as references, do that. Just be consistent.
If you are looking for something quick you can use the System properties, they are available to all classes. You can store a String value or if you need to store a list of 'stuff' you can use the System.Properties() method. This returns a 'Properties' object which is a HashTable. You can then store what ever you want into the table. It's not pretty but it's a quick way to have global properties. YMMV
I usually go for a singleton object that resides in a common project and contains a hashtable of itself keyed on namespace, resulting in a properties class for each.
Dependency injection is also a nice way of doing it.
I feel more comfortable when I have a static pointer to my in-memory properties. some times you want to reload properties in runtime, or other functionality that is easier to implement with a static reference.
just remember that no class is an island. a reusable class can have a client class to keep the core free of the singletone reference.
you can also use interfaces, just try not to overdo it.
Approache 2 is defenetly better.
Anyway, you should not let other class search through config object. You should injet config taken in the config object ouside the object.
Take a look at apache commons configuration for help with configuration Impl.
So in the main() you could have
MyObject mobj = new MyObject();
mobj.setLookupDelay(appConfig.getMyObjectLookupDelay);
mobj.setTrackerName(appConfig.getMyObjectTrackerName);
Instead of
MyObject mobj = new MyObject();
mobj.setConfig(appConfig);
where appConfig is a wrapper around the apache configuration library that do all the lookup of the value base on the name of the value in a config file.
this way your object become very easily testable.
Haven't done Java for a while, but can't you just put your properties into the java.lang.System properties? This way you can access the values from everywhere and avoid having a "global" property class.

Categories