Why does code in static block execute multiple times? - java

I have created a class in Spring boot to establish a global javers object that can be used by all classes. This is my code.
#Component
public class JaversInstance {
public static final Javers javers;
static
{
ConnectionProvider connectionProvider = new ConnectionProvider() {
#Override
public Connection getConnection() throws SQLException {
String url = "any_url";
Properties props = new Properties();
props.setProperty("user", "test");
props.setProperty("password", "test");
DriverManager.getConnection(url, props);
System.out.println("CONNECTION PROVIDER invoked");
return DriverManager.getConnection(url, props);
}
};
JaversSqlRepository sqlRepository = SqlRepositoryBuilder
.sqlRepository()
.withConnectionProvider(connectionProvider)
.withDialect(DialectName.MYSQL).build();
System.out.println("JAVERS instance creation");
javers = JaversBuilder.javers().registerJaversRepository(sqlRepository).build();
}
private JaversInstance() {
}
}
Output:
JAVERS instance creation
CONNECTION PROVIDER invoked
CONNECTION PROVIDER invoked
CONNECTION PROVIDER invoked
CONNECTION PROVIDER invoked
CONNECTION PROVIDER invoked
CONNECTION PROVIDER invoked
CONNECTION PROVIDER invoked
CONNECTION PROVIDER invoked
CONNECTION PROVIDER invoked
Can someone tell me what has happened here. Why the getConnection() is called so many times? Is this any kind of retry?

It happens as many times as the anonymous class of ConnectionProvider is loaded. The following code will help you understand it better:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Main {
static Comparator<Integer> comparator;
static {
comparator = new Comparator() {
#Override
public int compare(Object o1, Object o2) {
System.out.println("Hello");
return 0;
}
};
}
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(40);
list.add(20);
list.add(10);
list.add(30);
Collections.sort(list, comparator);
}
}
Output:
Hello
Hello
Hello

Although the ConnectionProvider is instantiated inside a static block, its overridden method is neither static (can't be) nor related to the static block itself but to the instance connectionProvider.
Basically, you implement a method of an anonymous class. I suppose the ConnectionProvider is an interface, then defining a class implementing the very same interface would be effectively the same as your code:
static
{
ConnectionProvider connectionProvider = new MyConnectionProvider();
}
The internals of the getConnection method is not bound to the static block, the instance connectionProvider itself is. There are multiple calls since the method has been invoked multiple times from an instance defined within the static block.

Related

Invoke of a method - logging as method declaring class

I'm currently using JBoss interceptors and Proxy classes for wrapping method invoking at runtime and log some statistics.
So said, having this code:
public class ProxyLoggingInterceptor <T> implements InvocationHandler {
private Logger logger = LoggerFactory.getLogger(ProxyLoggingInterceptor.class);
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
logger.info("%s.%s", t.getClass().getSimpleName(), method.getName());
}
}
the log will produce something like this:
12-11-2018 11:41.09,728 INFO (ProxyLoggingInterceptor) - [ANALYTICS]: MyClass.myMethod
However I'd like to show the logging declaring class as the logger entry, that is MyClass.
The desired result would be like:
12-11-2018 11:41.09,728 INFO (MyClass) - [ANALYTICS]: MyClass.myMethod
Is there any way that would not considered as a bad practice ?
Actually I am not into AOP based on dynamic proxies, I always use AspectJ where this kind of problem does not exist and it is easy to get the information you want because the original classes get modified. But having found the question anyway due to its aop tag and having played around a bit, I am trying to answer it:
package de.scrum_master.app;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.function.Function;
public class ProxyLoggingInterceptor<T> implements InvocationHandler {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.printf(
"%s.%s%n",
proxy.getClass().getGenericInterfaces()[0].getTypeName(),
method.getName()
);
return null;
}
public static void main(String[] args) {
ClassLoader classLoader = ProxyLoggingInterceptor.class.getClassLoader();
Map mapProxy = (Map) Proxy.newProxyInstance(
classLoader,
new Class[] { Map.class },
new ProxyLoggingInterceptor<Map>()
);
mapProxy.put("foo", 11);
Function functionProxy = (Function) Proxy.newProxyInstance(
classLoader,
new Class[] { Function.class },
new ProxyLoggingInterceptor<Function>()
);
functionProxy.apply("x");
Runnable runnableProxy = (Runnable) Proxy.newProxyInstance(
classLoader,
new Class[] { Runnable.class },
new ProxyLoggingInterceptor<Runnable>()
);
runnableProxy.run();
}
}
Console output:
java.util.Map.put
java.util.function.Function.apply
java.lang.Runnable.run
Is that what you want?

Wrapping a service in a SleepyProxy to simulate lag

I am attempting to wrap a service in a proxy to simulate lag during tests. The following class is meant to wrap an object and sleep the thread for 100ms for any invoked method.
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class SleepyProxy<T> implements InvocationHandler {
private T wrapped;
private SleepyProxy(T toWrap) {
this.wrapped = toWrap;
}
#SuppressWarnings({"unchecked", "rawtypes"})
public static <T> T createProxy(T toWrap) {
Object proxy = Proxy.newProxyInstance(
toWrap.getClass().getClassLoader(),
toWrap.getClass().getInterfaces(),
new SleepyProxy(toWrap));
return (T) proxy;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(wrapped, args);
nap();
return result;
}
private void nap() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
From my test class:
private MyService service = SleepyProxy.createProxy(ServiceProvider.getMyService());
Produces the following error:
java.lang.ClassCastException: com.sun.proxy.$Proxy33 cannot be cast to com.example.service.MyService;
Please Note:
I am using Spring Framework and JUnit4
Test class annotated with #RunWith(SpringJUnit4ClassRunner.class)
I'm learning Spring; I'm unsure if I need to be using a Spring InvocationHandler / Proxy service
Why am I having issues casting to MyService? All object values seem to line up when debugging. Is there a better way I can go about simulating lag on my services? (Aside from making a 'test service' for each).
Thanks for your help!
Problem is that MyService is a class, and Proxy.newProxyInstance creates object that implements interface you provide in second argument. To have it working MyService needs to implement interface so:
class MyService implements ServiceInterface
And later use your proxy like this:
ServiceInterface service = SleepyProxy.createProxy(ServiceProvider.getMyService());
Proxy.newProxyInstance has nothing to do with MyService class, it will only create object that will run InvocationHandler.invoke when you will call method on it.

Abstract factory pattern and HikariCP

I'm currently using a pool connection(Hikari) and an abstract factory pattern to implement my MySQL queries in Java like this:
MySqlFactoryDAO.java
public class MySqlFactoryDAO extends FactoryDAO {
private static HikariDataSource connPool_;
public static Connection createConnection() throws SQLException {
if (connPool_ == null) {
// Load database configuration
PropertiesFile props = FactoryConfig.getConfig().getDatabaseProperties();
connPool_ = new HikariDataSource();
connPool_.setJdbcUrl(props.getString(Params.DB_URL,""));
connPool_.setUsername(props.getString(Params.DB_USER,"root"));
connPool_.setPassword(props.getString(Params.DB_PASSWORD,"root"));
}
return connPool_.getConnection();
}
//-------------------------------------------------------------------------
public ProductDAO getProductDAO() {
return new ProductMySQLFactoryDAO();
}
}
ProductMySQLFactoryDAO.java
public class ProductMySQLFactoryDAO implements ProductDAO {
public int insertProduct(String name) {
...
Connection conn = MySqlFactoryDAO.createConnection();
...
}
}
I was wondering if this code is thread safe and I think that there is a problem at the time of initialization of coonPool_. I have read things like "Initialization-on-demand_holder_idiom" in wikipedia but I am not sure about it. Does anyone have a better implementation of this to solve this problem or just a better new one?
No, it's not thread-safe. Two threads might call createConnection() concurrently, both see the pool as null, and both create a new DataSource.
The method needs to be synchronized. Or the pool must be created at class initializing time:
private static final HikariDataSource DATA_SOURCE = createDataSource();
Your connPool_ field should be private, too.

Closeing a static resource in Java

I have a question about closing resources (AutoCloseable or not) that are static members of a Java class. In my particular situation I have a class that manages connections to a MongoDB instance using a static MongoClient instance variable. How would I ensure that this client is closed as the documentation recommends when my application terminates? I am using this class as part of the back end to a Java webapp which is run in a container (Tomcat 7). I could not override the Object's finalize() method to close the client because that is called on an instance of the class and would have no effect on static members correct? Here is my example code:
public class MyManager {
//This needs to be closed when the application terminates
private static MongoClient CLIENT;
static {
...
CLIENT = new MongoClient("localhost", 27017);
...
}
public static DB getSomeDB(String dbName) {
return CLIENT.getDB(dbName);
}
//more factory methods
...
//Would this work?
#Override
protected void finalize() throws Throwable {
CLIENT.close();
}
}
Can someone tell me how to best handle this situation and in general with resources such as a database connection or JDBC driver? Thanks!
We are using Spring and simply create a bean which calls the close() method once it's being destroyed:
#Bean(name = "mongoClient", destroyMethod = "close")
public MongoClient mongoClient() throws MongoException, UnknownHostException {
...

Test class with a new() call in it with Mockito

I have a legacy class that contains a new() call to instantiate a LoginContext object:
public class TestedClass {
public LoginContext login(String user, String password) {
LoginContext lc = new LoginContext("login", callbackHandler);
}
}
I want to test this class using Mockito to mock the LoginContext as it requires that the JAAS security stuff be set up before instantiating, but I'm not sure how to do that without changing the login() method to externalize the LoginContext.
Is it possible using Mockito to mock the LoginContext class?
For the future I would recommend Eran Harel's answer (refactoring moving new to factory that can be mocked). But if you don't want to change the original source code, use very handy and unique feature: spies. From the documentation:
You can create spies of real objects. When you use the spy then the real methods are called (unless a method was stubbed).
Real spies should be used carefully and occasionally, for example when dealing with legacy code.
In your case you should write:
TestedClass tc = spy(new TestedClass());
LoginContext lcMock = mock(LoginContext.class);
when(tc.login(anyString(), anyString())).thenReturn(lcMock);
I am all for Eran Harel's solution and in cases where it isn't possible, Tomasz Nurkiewicz's suggestion for spying is excellent. However, it's worth noting that there are situations where neither would apply. E.g. if the login method was a bit "beefier":
public class TestedClass {
public LoginContext login(String user, String password) {
LoginContext lc = new LoginContext("login", callbackHandler);
lc.doThis();
lc.doThat();
return lc;
}
}
... and this was old code that could not be refactored to extract the initialization of a new LoginContext to its own method and apply one of the aforementioned solutions.
For completeness' sake, it's worth mentioning a third technique - using PowerMock to inject the mock object when the new operator is called. PowerMock isn't a silver bullet, though. It works by applying byte-code manipulation on the classes it mocks, which could be dodgy practice if the tested classes employ byte code manipulation or reflection and at least from my personal experience, has been known to introduce a performance hit to the test. Then again, if there are no other options, the only option must be the good option:
#RunWith(PowerMockRunner.class)
#PrepareForTest(TestedClass.class)
public class TestedClassTest {
#Test
public void testLogin() {
LoginContext lcMock = mock(LoginContext.class);
whenNew(LoginContext.class).withArguments(anyString(), anyString()).thenReturn(lcMock);
TestedClass tc = new TestedClass();
tc.login ("something", "something else");
// test the login's logic
}
}
EDIT:
Modern versions of Mockito provide similar functionality without needing the extra PowerMock library with the mockito-inline dependency (instead of the mockito-core dependency):
public class TestedClassTest {
#Test
public void testLogin() {
try (MockedConstruction<LoginContext> mockedConstruction =
Mockito.mockConstruction(LoginContext.class)) {
TestedClass tc = new TestedClass();
tc.login("something", "something else");
// test the login's logic
}
}
}
You can use a factory to create the login context. Then you can mock the factory and return whatever you want for your test.
public class TestedClass {
private final LoginContextFactory loginContextFactory;
public TestedClass(final LoginContextFactory loginContextFactory) {
this.loginContextFactory = loginContextFactory;
}
public LoginContext login(String user, String password) {
LoginContext lc = loginContextFactory.createLoginContext();
}
}
public interface LoginContextFactory {
public LoginContext createLoginContext();
}
public class TestedClass {
public LoginContext login(String user, String password) {
LoginContext lc = new LoginContext("login", callbackHandler);
lc.doThis();
lc.doThat();
}
}
-- Test Class:
#RunWith(PowerMockRunner.class)
#PrepareForTest(TestedClass.class)
public class TestedClassTest {
#Test
public void testLogin() {
LoginContext lcMock = mock(LoginContext.class);
whenNew(LoginContext.class).withArguments(anyString(), anyString()).thenReturn(lcMock);
//comment: this is giving mock object ( lcMock )
TestedClass tc = new TestedClass();
tc.login ("something", "something else"); /// testing this method.
// test the login's logic
}
}
When calling the actual method tc.login ("something", "something else"); from the testLogin() {
- This LoginContext lc is set to null and throwing NPE while calling lc.doThis();
Not that I know of, but what about doing something like this when you create an instance of TestedClass that you want to test:
TestedClass toTest = new TestedClass() {
public LoginContext login(String user, String password) {
//return mocked LoginContext
}
};
Another option would be to use Mockito to create an instance of TestedClass and let the mocked instance return a LoginContext.
In situations where the class under test can be modified and when it's desirable to avoid byte code manipulation, to keep things fast or to minimise third party dependencies, here is my take on the use of a factory to extract the new operation.
public class TestedClass {
interface PojoFactory { Pojo getNewPojo(); }
private final PojoFactory factory;
/** For use in production - nothing needs to change. */
public TestedClass() {
this.factory = new PojoFactory() {
#Override
public Pojo getNewPojo() {
return new Pojo();
}
};
}
/** For use in testing - provide a pojo factory. */
public TestedClass(PojoFactory factory) {
this.factory = factory;
}
public void doSomething() {
Pojo pojo = this.factory.getNewPojo();
anythingCouldHappen(pojo);
}
}
With this in place, your testing, asserts and verify calls on the Pojo object are easy:
public void testSomething() {
Pojo testPojo = new Pojo();
TestedClass target = new TestedClass(new TestedClass.PojoFactory() {
#Override
public Pojo getNewPojo() {
return testPojo;
}
});
target.doSomething();
assertThat(testPojo.isLifeStillBeautiful(), is(true));
}
The only downside to this approach potentially arises if TestClass has multiple constructors which you'd have to duplicate with the extra parameter.
For SOLID reasons you'd probably want to put the PojoFactory interface onto the Pojo class instead, and the production factory as well.
public class Pojo {
interface PojoFactory { Pojo getNewPojo(); }
public static final PojoFactory productionFactory =
new PojoFactory() {
#Override
public Pojo getNewPojo() {
return new Pojo();
}
};
I happened to be in a particular situation where my usecase resembled the one of Mureinik but I ended-up using the solution of Tomasz Nurkiewicz.
Here is how:
class TestedClass extends AARRGGHH {
public LoginContext login(String user, String password) {
LoginContext lc = new LoginContext("login", callbackHandler);
lc.doThis();
lc.doThat();
return lc;
}
}
Now, PowerMockRunner failed to initialize TestedClass because it extends AARRGGHH, which in turn does more contextual initialization... You see where this path was leading me: I would have needed to mock on several layers. Clearly a HUGE smell.
I found a nice hack with minimal refactoring of TestedClass: I created a small method
LoginContext initLoginContext(String login, CallbackHandler callbackHandler) {
new lc = new LoginContext(login, callbackHandler);
}
The scope of this method is necessarily package.
Then your test stub will look like:
LoginContext lcMock = mock(LoginContext.class)
TestedClass testClass = spy(new TestedClass(withAllNeededArgs))
doReturn(lcMock)
.when(testClass)
.initLoginContext("login", callbackHandler)
and the trick is done...

Categories

Resources