Usually I define logger like this:
private static final Logger logger = LoggerFactory.getLogger(MyClass.class);
But when using #Inject we must use non-static and non-final field, like:
#Inject
private Logger logger;
i.e. logger will be created in each instance of this class, also logger is mutable. May be exist some way to make logger static? Also how I can bind logger to certain class (I use send the class object when creating logger object from factory LoggerFactory.getLogger(MyClass.class);, how to create logger in same way using injecting ? )?
Please check the Custom Injections on Guice wiki, there is a complete Log4J example.
EDIT: You can use either a static field or a final field for your logger, but not a static final one. This is a Java limitation.
Also be wary that:
Injecting final fields is not recommended because the injected value may not be visible to other threads.
Haven't tested that but the code in the article should work fine for static fields, although you could improve it by getting rid of MembersInjector and doing all of it in the TypeListener (since a static field needs to be set only once).
Using requestStaticInjection() will force you to list all your classes in a module file - not a good idea, as you will soon forget to add one.
OTOH if you just want to support JUL you might be better of using the built-in support (as mentioned by Jeff, I assumed you didn't want a general answer, since you didn't mention JUL specifically in your question).
When designing your application for dependency injection, typically the best practice is to avoid static fields and methods as much as possible. This is so that your dependencies are clearer, and so it's easier to replace your real dependencies with other instances during tests and as your application evolves. The ideal behavior, therefore, is to avoid static methods and fields (including loggers) as much as possible.
Guice, however, does allow for marking fields static, and requesting injection of static fields when the Injector is created. The fields will need to remain mutable--final doesn't mean "final except for Guice".
public class YourClass {
#Inject static Logger logger;
/* ... */
}
public class YourModule extends AbstractModule {
#Override public void configure() {
/* YourClass.logger will work once you create your Injector. */
requestStaticInjection(YourClass.class);
}
}
Guice automatically provides java.util.logger.Logger instances for you with the class name embedded into it, but that's only because of a special case coded into Guice. If you want a special logger, as in this SO question, you'll need to investigate the Custom Injections to which Jakub linked--but if the whole goal is to centralize logger creation so you can control it in one place, you can just refactor that into a static factory outside of Guice too.
#LogToFile
public class YourClass {
private static final Logger logger = YourLoggerFactory.create(YourClass.class);
/* ... */
}
public class YourLoggerFactory {
private YourLoggerFactory { /* do not instantiate */ }
public Logger create(Class<?> clazz) {
if (clazz.getAnnotation(LogToFile.class) != null) {
return someImplementation(new File(...));
} else {
return someOtherImplementation();
}
}
}
Related
I know from this solution I can autowired static fields in spring.
#Component
public class AdminUtil {
private static IAirportService airportService;
#Autowired
public AdminUtil(IAirportService portService) {
AdminUtil.airportService = portService;
}
...
}
But sonar says: Static fields should not be updated in constructors (RSPEC-3010)
Is there any alternate way to autowired static fields in spring? Or do I ignore this?
Spring's idea is that Components get instantiated once by default and reused throughout the application. This should be save as long as the components don't hold state.
Considering your code sample the easiest solution would be to not make the airportService static.
I'm trying to improve my optimization skills in Java. In order to achieve that, I've got an old program I made and I'm trying my best to make it better. In this program I'm using SL4J for logging. To get the logger I did:
private static final Logger logger = LoggerFactory.getLogger(this.getClass().getName());
At the time I wrote the code, I thought this was the best option, because I remove a reference to the class name(which may be refactored). But now I'm not so sure anymore...
private static final Logger logger = LoggerFactory.getLogger(ClassName.class);
On the other side, keeps the reference to the class name, but it removes one method call. This may not be a big improvement in performance for one class, but when you have lots of class, this may be something.
So my question is:
Which approach is better? Using the class name or getting it through reflection?
Please, motivate your answer with pro and cons. Thank you.
Late entry!
As I am likely to be searching for this in the future.
There is a way to create copy/paste friendly Logger instances (granted this is almost never a good reason to do something!) by using Java 7's MethodHandles class.
private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
I'll share my opinion here. I would say that this is the case that you shouldn't be bothered from the performance point of view. Probably in the code there are parts that can be optimized much more than this thing :)
Now, regarding your question. Take a look on LoggerFactory's code
Note that getLogger(Class<?> name) just calls the overloaded method:
Logger logger = getLogger(clazz.getName());
And makes some additional calculations. So the method with String is obviously slightly faster.
In general the pattern is to maintain the Logger reference as a static field in the class, something like this:
public class SomeClass {
private static final Logger LOG = LoggerFactory.getLogger(SomeClass.class);
}
In this case you can't really use this.getClass() because this doesn't actually exists (you're running in a static context).
From my experience its better to use the ClassName.getClass() as a parameter unless you really want to use the same logger from different classes. In such a case you better use some logical constant that denotes the logger.
For example, let's say you're trying to use 3 different classes to access the database.
So you create logger 'DB', assign a file appender that will write to database.log and you want to reuse the same logger among these 3 different classes.
So you should use the following code:
public class SomeClass {
private static final Logger LOG = LoggerFactory.getLogger("DB");
}
Hope this helps
What I usually do is
private static final Logger logger = LoggerFactory.getLogger(ClassName.class);
However, the idiom
protected final Logger log = LoggerFactory.getLogger(getClass());
is equally common. In this question you can find more info about these conventions.
I prefer
Logger logger = LoggerFactory.getLogger(ClassName.class);
Because
this.getClass()
Can be override by one of class children and you will see child class name in log. Sometimes it can be confusing because log actually is performed in parent class
When in static context you can't use LoggerFactory.getLogger(getClass()) OR LoggerFactory.getLogger(this.getClass().getName())
And then you have to use LoggerFactory.getLogger(ClassName.class)
Anyways I prefer Lombok's #Log4j2 , less code and does the job : https://projectlombok.org/api/lombok/extern/log4j/Log4j2.html
If you don't want to write the class name every time you declare a logger, you can use the following utility method:
public static org.slf4j.Logger getLogger() {
final Throwable t = new Throwable();
t.fillInStackTrace();
return LoggerFactory.getLogger(t.getStackTrace()[1].getClassName());
}
The method can be used tis way:
private static final Logger LOG = TheClassContainingTheMethod.getLogger();
With such an approach, the logger declaration is always the same for all the classes.
Use this
private final Logger logger = LoggerFactory.getLogger(this.getClass());
}
// logic
try
{
// todo
}
catch (NullPointerException e) {
logger.error("Error:-" + e.getMessage());
return ResponseUtil.errorResponse(e.getMessage());
}
catch (Exception e) {
logger.error("Error:-" + e.getMessage());
return ResponseUtil.errorResponse(e.getMessage());
}
To add a field to some specific class with aspectj we do
package com.test;
public class MyClass {
private String myField;
}
public aspect MyAspect
{
private String MyClass.myHiddenField;
}
How do we add a field to a class that is annotated with some custom annotation?
example usage : if class is annotated with #CustomLoggable add a Logger field and some methods.
or
if method has the #ReadLocked annotation then class will have a ReentrantReadWriteLock field and the appropriate logic injected, etc.
Actually you cannot make inter-type declarations (ITD) on annotation types, i.e. you need to know concrete class names in order to declare static or non-static members or methods directly.
The usual workaround is:
Create an interface with all the methods you need.
Provide implementations for each interface method.
Make each annotated type implement the interface via ITD.
Now if you also want to add a static member such as a logger to all annotated types, again if you do not know the exact class names you need to use a workaround:
Create an aspect holding the desired member(s). Let's call it LoggerHolder in this example.
Make sure that one aspect instance per target class is created instead of the default singleton aspect instance. This is done via pertypewithin.
In order to avoid runtime exceptions you must not initialise the members directly via Logger logger = ... but need to do it lazily, waiting until after the target type's static initialisation phase is finished.
You also need to provide an accessor method like LoggerHolder.getLogger() in the aspect and call it whenever necessary.
In order to hide all the ugly aspect stuff from the end user I recommend to add yet another accessor method LoggableAspect.getLogger() (same method name for convenience) to the ITD interface mentioned above and provide a method implementation extracting the member reference from the aspect instance via LoggerHolder.aspectOf(this.getClass()).getLogger().
Attention: I am using two concepts at once here, mixing them in one application because you asked for both static members and non-static methods added to annotated classes:
Helper interface + implementation added to your core code via ITD
Holder aspect declaring member(s) and associated with target classes via pertypewithin in order to emulate static members
Now here is some sample code:
Annotation:
package de.scrum_master.app;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
#Retention(RetentionPolicy.RUNTIME)
public #interface CustomLoggable {}
Two classes, one bearing the annotation and one not bearing it:
package de.scrum_master.app;
public class OrdinaryClass {
public void doSomething() {
System.out.println("Logging some action directly to console");
}
}
package de.scrum_master.app;
import java.util.logging.Level;
#CustomLoggable
public class AnnotatedClass {
public void doSomething() {
getLogger().log(Level.INFO, "Logging some action via ITD logger");
getLogger().log(Level.INFO, someOtherMethod(11));
}
}
As you can see, the second class uses two methods which have not been declared directly within the class: getLogger() and someOtherMethod(int). Both of them will be declared via ITD further below, the former providing access to the pseudo-static member and the latter being just another method you want declared on each annotated class.
Aspect holding an instance of the pseudo-static member:
package de.scrum_master.aspect;
import java.util.logging.Logger;
import de.scrum_master.app.CustomLoggable;
public aspect LoggerHolder
pertypewithin(#CustomLoggable *)
{
private Logger logger;
after() : staticinitialization(*) {
logger = Logger.getLogger(getWithinTypeName());
}
public Logger getLogger() {
return logger;
}
}
As I said earlier, please note the usage of pertypewithin and staticinitialization. Another convenient thing is to use the aspect's getWithinTypeName() method in order to get the target class name for naming the logger.
Aspect declaring an interface + implementation and applying it to all target types:
package de.scrum_master.aspect;
import java.util.logging.Logger;
import de.scrum_master.app.CustomLoggable;
public aspect LoggableAspect {
public static interface Loggable {
Logger getLogger();
String someOtherMethod(int number);
}
declare parents : (#CustomLoggable *) implements Loggable;
public Logger Loggable.getLogger() {
return LoggerHolder.aspectOf(this.getClass()).getLogger();
}
public String Loggable.someOtherMethod(int number) {
return ((Integer) number).toString();
}
}
For simplicity, I just declared the interface as a static nested type within the aspect. You can also declare the interface separately, but here you see it in its context which for me is preferable.
The key thing here is the declare parents statement making each target class implement the interface. The two method implementations at the end show how to provide "normal" method implementations as well as how to access the logger from the holder aspect via aspectOf.
Driver class with entry point:
Last, but not least, we want to run the code and see if it does what we want.
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
new OrdinaryClass().doSomething();
new AnnotatedClass().doSomething();
}
}
Console output:
Logging some action directly to console
Mrz 15, 2015 11:46:12 AM de.scrum_master.app.AnnotatedClass doSomething
Information: Logging some action via ITD logger
Mrz 15, 2015 11:46:12 AM de.scrum_master.app.AnnotatedClass doSomething
Information: 11
VoilĂ ! Logging works, the Logger has a nice name de.scrum_master.app.AnnotatedClass and calling the two interface methods works as expected.
Alternative approach:
Since AspectJ 1.8.2 annotation processing is supported, see also this blog post. I.e. you could use APT in order to generate one aspect per annotated type and introduce static members and additional methods directly without any tricks such as per-type instantiation, accessor methods members within holder aspect instances and interfaces. This comes at the cost of an additional build step, but I think it would be a very neat and straightforward way to solve your problem. Let me know if you have any difficulty understanding the examples and need more help.
You can create a pointcut for any type with a particular annotation. See Join Point Matching based on Annotations.
I need to get class and method names to Log4j logger. What is the best way of doing that? Also I would like to create one instance of logger for whole application - it is quite boring to declare logger in each class. What is the way to solve these problems.
You can use %C and %M placeholders in your PatternLayout. Please be advised, their use is not recommended for performance reasons.
There are several ideas on how to avoid declaring loggers for each class. For example, if creating a common base class is a viable option, you can declare a protected final logger like this:
abstract class Base {
protected final Logger logger = Logger.getLogger(getClass());
}
class Concrete extends Base {
public void testLogger() {
logger.info("It works!");
}
}
Or, you may try injecting loggers with a dependency injection framework such as Weld.
Actually, creating one Logger for whole application, is not a good idea at all. It's easy to mess up loggers, levels of logging, configuration, etc.
But, if you still want it, you could create a logger instance in main method, and pass it for each of the class (e.g. using setLogger() in every class you use or passing as argument to class constructor). But again, is 100% bad idea to do this.
make your Logger Instance static
Every class has its own Logger => Logger.getLogger(xyz.class)
Use 2. than you can configure log4j
I'm creating a library that will be included as a jar, so it won't contain a main method. I'm wondering what is the best practice for bootstrapping Guice in this case. I have one top level singleton.
public class TestManager
{
private TestManager()
{
}
public static TestManager getInstance()
{
// construct and return singleton
}
public void createSomeObjects()
{
}
}
Where should I bootstrap Guice? I was thinking that in the constructor that I could call Guice.createInjector(new Module()); but it wouldn't inject any of the objects created in createSomeObjects().
Is there a common way to do this when you don't have a main method()?
Cheers.
Much like logging configurations, if this is a true library then your options are pretty much this:
Tell the library user that they are responsible for bootstrapping Guice themselves.
Provide a library initialization method that takes care of bootstrapping Guice if they want to use your library
Trying to make the library super-smart to do self-configuration often ends up with somewhat inflexible, hard to test class hierarchies.
If you're just using Guice in the scope of your library and not for the whole application then you could use a static block in the TestManager class.
This strategy assumes that the application is going to call TestManager.getInstance() at some point and that it is the only entry point into your API.
#Singleton
class TestManager {
private static final TestManager INSTANCE;
static {
INSTANCE = Guice.createInjector(new Module()).getInstance(TestManager.class);
}
private TestManager() {
}
public static TestManager getInstance() {
return INSTANCE;
}
#Inject
public void createSomeObjects(YourDependencies ...) {
// Do something with dependencies
}
}
This is not what you should do, but what you could do:
Let key classes in your library extend or otherwise reference a class that initializes everything in a static block. This is a very dirty hack, but if you make sure your api can't be accessed without the classloader loading your initializer class you should be on the safe side.
You could make it a bit cleaner if you used AspectJ and injected a private Member of the initializer type into all classes in your library (without touching the java code), but it would still be a hack.