My JSF Books/Videos My JSF Tutorials OmniFaces/JSF PPTs
JSF 2.3 Tutorial
JSF Caching Tutorial
JSF Navigation Tutorial
JSF Scopes Tutorial
JSF Page Author Beginner's Guide
OmniFaces 2.3 Tutorial Examples
OmniFaces 2.2 Tutorial Examples
JSF Events Tutorial
OmniFaces Callbacks Usages
JSF State Tutorial
JSF and Design Patterns
JSF 2.3 New Features (2.3-m04)
Introduction to OmniFaces
25+ Reasons to use OmniFaces in JSF
OmniFaces Validators
OmniFaces Converters
JSF Design Patterns
Mastering OmniFaces
Reusable and less-verbose JSF code

My JSF Resources ...

Java EE Guardian
Member of JCG Program
Member MVB DZone
Blog curated on ZEEF
OmniFaces is an utility library for JSF, including PrimeFaces, RichFaces, ICEfaces ...

[OmniFaces Utilities] - Find the right JSF OmniFaces 2 utilities methods/functions

Search on blog

Petition by Java EE Guardians

Twitter

marți, 14 iunie 2016

CDI-JSF: Inject a Java logger via a CDI producer method

Most commonly, when we need to log something via a Java logger, we write something like this:

private static final Logger LOG = Logger.getLogger(MyClass.class.getName());

Check out the part of the code that is highlighted in red. Well, that part tell us that the above line of code is dependent of the class name where it appears, and this may rise refactoring issues. Moreover, this line must appear in each class that want to use the logger, which is a little bit verbose.

But, CDI comes with a very handy and bidder feature that consist in the fact that we can easily obtained information about the injection point of an artifact. For example, an instance of InjectionPoint can access metadata of the class where the artifact is injected. A bean without an explicit scope (so, having the @Dependent default scope) can inject an instance of InjectionPoint. CDI will take care of providing this instance for us, so all we need to do is to exploit its methods.

Now, if we take a look at the logger case, we can  easily conclude that the logger is dependent of a metadata, or more exactly is dependent on the class name. So, if we write something like below, we can actually obtain the desired metadata in an @Dependent bean:

public class MyLogger {

 @Produces
 Logger produceLogger(InjectionPoint injectionPoint) {

  // get the field injection (e.g. fooLog, buzzLog, bizzLog)      
  Member field = injectionPoint.getMember();
  System.out.println("Member: " + field);

  // get the class containing the field injection
  Class<?> fieldClass = field.getDeclaringClass();
  System.out.println("Class: " + fieldClass);

  // get the class name
  String className = fieldClass.getName();
  System.out.println("Class name: " + className);

  return Logger.getLogger(className);

  // or shortly:
  return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
 }
}

First, we declare the produceLogger()method as a CDI producer method via the @Produces annotation, highlighted in blue. By making this method a producer method, we allow the return value of the method -in this case a Logger- to be injected.

As you can see, the part highlighted in red is responsible to use the instance of InjectionPoint for extracting the name of the class where the artifact is injected. Further, we use the extracted class name to create a logger for that class and return it.

So, now we can simply use a logger via injection. For example, we can inject it in FooBean:

@Named
@RequestScoped
public class FooBean {

 @Inject
 Logger fooLog;

 public void logFooAction() {
  fooLog.info("Log message from FooBean !");
 }
}

Or, in BuzzBean:

@Named
@RequestScoped
public class BuzzBean {

 @Inject
 Logger buzzLog;

 public void logBuzzAction() {
  buzzLog.info("Log message from BuzzBean !");
 }
}

Or, in BizzBean:

@Named
@RequestScoped
public class BizzBean {

 @Inject
 Logger bizzLog;

 public void logBizzAction() {
  bizzLog.info("Log message from BizzBean !");
 }
}

Or, in ... any other bean.

Well, a possible output will be:


The complete example is available here.

4 comentarii :

  1. Nice, but how do I test the method logBuzzAction()? In a simple JUnit test I would run into an NullPointerException (because bizzLog is null), wouldn't I?

    RăspundețiȘtergere
    Răspunsuri
    1. You can try to use CDI alternatives (@Alternative) and/or mock test.

      Ștergere
    2. Also, you can try Jglue (http://jglue.org/cdi-unit-user-guide/)

      Ștergere
    3. Check this: http://www.omnifaces-fans.org/2016/06/cdi-jsf-testing-cdi-code.html

      Ștergere

JSF BOOKS COLLECTION

Postări populare

Follow by Email

Visitors Starting 4 September 2015

Locations of Site Visitors