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);
}
Related
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)
My class uses a static local variable of org.slf4j.Logger. Is there some clever way of replacing this with a mock object for my testing? I'm thinking my best option is for MyClass to expose a setter?
Also, how can I mock the Logger object? I'd like to mock it such that when LOGGER.error(string, exception) is called I'd like to validate the error String.
public class MyClass {
private static Logger LOGGER = LoggerFactory.getLogger(MyClass.class);
How can you get a mock object in at runtime when it is not created/initialized in the class you are testing, it is not static (singleton pattern), or you don't have some sort of test constructor to hook into?
In a class that I am writing some unit testing for, I have come across a scenario I haven't encountered/solved yet. I have a JMS resource (a QueueConnectionFactory for reference, but it shouldn't matter), that is a private variable of the class I am testing. Since it has the javax.annotation.Resource annotation, at runtime it is assumed to be available. During testing, it is not, which creates the need for mocking this object.
It is not a static class and is not being used in a static way, if it was I could easily mock using the various static mocking methods I have run into. Since the resource is never created locally (in a constructor or even in a test constructor), I have no way of passing in a Mock object so that at runtime of the test, the mock is used instead of the actual object. How can I mock this Resource so that when the test executes, it will be used in place of the private #Resource object in the class I am testing?
For reference, the code is calling createConnection() on the QueueConnectionFactory which is throwing a null pointer exception since the Factory has not been initialized/mocked.
#Stateless
public class Example{
#Resource(name = "jms/exampleQCF")
private QueueConnectionFactory queueFactory;
...
public void testMe(){
Connection connection = queueFactory.createConnection();
...
}
}
After a lot more hunting around and looking at all the options Mockito/Powermock had to offer, I found the solution (which I will share in case others run into this same issue).
When you have private member variables that are never initialized (and just assumed created in other places), you can use the #InjectMocks annotation to "inject" Mocks you want into your class you are testing.
Add a variable in your test class for the class you are testing, and give it the annotation #InjectMocks (org.Mockito.InjectMocks).
Use #Mock annotations to setup the mocks you want to inject. Use the #Mock (name = "privateVariableNameHere") name property to map the Mock object to the private variable inside your class you are testing.
In either a setup function or before you call your class, initialize the mocks. The easiest way I have found is to use a "setup" method with the #Before annotation. Then inside there call MockitoAnnotations.initMocks(this); to quickly initialize anything with the #Mock annotation.
Define your Mock functionality in your test method (before calling the method you are testing).
Using the #InjectMock object, call your method you are testing... the mocks SHOULD be hooked in and working as defined in the earlier steps.
So for the example class I use above, the code to test/mock would have Connection returned as a mock which you can do whatever with. Based on the example above in my question, this is what the code would look like:
#RunWith(PowerMockRunner.class)
#PrepareForTest({/* Static Classes I am Mocking */})
public class ExampleTest {
#Mock (name = "queueFactory") //same name as private var.
QueueConnectionFactory queueFactoryMock;
#Mock
Connection connectionMock; //the object we want returned
#InjectMocks
Example exampleTester; //the class to test
#Before
public void setup(){
MockitoAnnotations.initMocks(this); // initialize all the #Mock objects
// Setup other Static Mocks
}
#Test
public void testTestMe(){
//Mock your objects like other "normally" mocked objects
PowerMockito.when(queueFactoryMock.createConnection()).thenReturn(connectionMock);
//...Mock ConnectionMock functionality...
exampleTester.testMe();
}
}
Several approaches here:
ReflectionTestUtils of Spring Testing framework: ReflectionTestUtils.setField(objectToTest, "privateFieldName", mockObjectToInject);. With this you don't introduce another dependency.
org.mockito.internal.util.reflection.FieldSetter.
PowerMock.Whitebox.setInternalState() to mock a private field.
If you need to mock internal local variable creation, use PowerMockito.whenNew(Foo.class).withNoArguments().thenReturn(foo);. Very, very useful. Cannot find other ways to do the same.
With only Mockito you cannot mock local variable creation, because when(any(Foo.class) does not work; will return null. It compiles but does not work.
References:
Mockito: Mock private field initialization
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.