Monthly Archives: June 2011
Static Field Injection In Spring
Injecting static fields in a spring bean doesn’t work by simply adding @Autowired annotation as below.
@Component public class MessageHelper { @Autowired private static MessageBean messageBean; public static void msg() { messageBean.display(); } }
It works either by having constructor or setter based injection.
@Component public class MessageHelper { private static MessageBean messageBean; @Autowired private void setMessageBean(MessageBean messageBean) { MessageHelper.messageBean = messageBean; } public static void msg() { messageBean.display(); } }
Database Connections Are Performance Expensive
While reading the Data Access Handbook I came across some facts about database connections. These connections are established by any JEE application to the database server.
- Creating a connection is performance-expensive compared to all other tasks a database application can perform.
- Open connections use a substantial amount of memory on both the database server and database client machines.
- Establishing a connection takes multiple network round trips to and from the database server.
- Opening numerous connections can contribute to out-of-memory conditions, which might cause paging of memory to disk and, thus, overall performance degradation.
- In today’s architectures, many applications are deployed in connection pooled environments, which are intended to improve performance.However, many times poorly tuned connection pooling can result in performance degradation. Connection pools can be difficult to design, tune, and monitor.
Read the rest of this entry
Implicit escape of “this” reference
One of the prerequisite in making an object immutable include making sure that the this reference isn’t allowed to escape during creation. This point is also referenced in the famous Java Concurrency In Practice book. Section 3.2 of the book states
“A mechanism by which an object or its internal state can be published is to publish an inner class instance, as shown in ThisEscape in Listing 3.7. When ThisEscape publishes the EventListener, it implicitly publishes the enclosing ThisEscape instance as well, because inner class instances contain a hidden reference to the enclosing instance. ”
public class ThisEscape { private final int num; public ThisEscape(EventSource source) { source.registerListener( new EventListener() { public void onEvent(Event e) { doSomething(e); } }); num = 42; } private void doSomething(Event e) { if (num != 42) { System.out.println("Race condition detected at " + new Date()); } } }
The above code creates issues in cases where for e.g. EventSource starts a concurrent execution which leads to the creation of the events before the constructor of ThisEscape completes. What this means is that the doSomething method gets called before the constructor of ThisEscape ends. Like any other method the doSomething() method, as shown above, could access the state of ThisEscape class assuming the object is in the consistent state.
To give an idea the EventSource code could look similar to
import java.util.concurrent.atomic.*; public class EventSource extends Thread { private final AtomicReference<EventListener> listeners = new AtomicReference<EventListener>(); public void run() { while (true) { EventListener listener = listeners.getAndSet(null); if (listener != null) { listener.onEvent(null); } } } public void registerListener(EventListener eventListener) { listeners.set(eventListener); } }
So publishing an object from within its constructor can publish an incompletely constructed object. This is true even if the publication is that last statement in the constructor because the Java Memory Model (JMM) allows reordering of the statements. Thus the code might be optimized in such a way that the “this” reference escapes earlier.
To test the above explained race condition you could execute
public class ThisEscapeTest { public static void main(String[] args) { EventSource es = new EventSource(); es.start(); while(true) { new ThisEscape(es); } } }
One of the solutions mentioned in the Java Concurrency In Practice book to the above problem is to use static factory method
public class SafeListener { private final EventListener listener; private SafeListener() { listener = new EventListener() { public void onEvent(Event e) { doSomething(e); } }; } public static SafeListener newInstance(EventSource source) { SafeListener safe = new SafeListener(); source.registerListener(safe.listener); return safe; } }
Thanks to the Java Specialist news letters for providing details on this topic.
Sonar PMD Plugin – Running in JDK 1.4 mode
If you are analyzing your project using sonar-runner (version 1.0) you might see the below exception
[ERROR] Fail to execute PMD. Following file is ignored: <path-to-java-file> net.sourceforge.pmd.ast.ParseException: Can't use static imports when running in JDK 1.4 mode! at net.sourceforge.pmd.ast.JavaParser.checkForBadStaticImportUsage(JavaParser.java:26) [pmd-4.2.5.jar:na] at net.sourceforge.pmd.ast.JavaParser.ImportDeclaration(JavaParser.java:248) [pmd-4.2.5.jar:na] at net.sourceforge.pmd.ast.JavaParser.CompilationUnit(JavaParser.java:124) [pmd-4.2.5.jar:na] at net.sourceforge.pmd.parsers.Java14Parser.parse(Java14Parser.java:23) [pmd-4.2.5.jar:na] at net.sourceforge.pmd.PMD.processFile(PMD.java:98) [pmd-4.2.5.jar:na] at net.sourceforge.pmd.PMD.processFile(PMD.java:75) [pmd-4.2.5.jar:na] at org.sonar.plugins.pmd.PmdExecutor.execute(PmdExecutor.java:70) [sonar-pmd-plugin-2.8.jar:na] at org.sonar.plugins.pmd.PmdSensor.analyse(PmdSensor.java:45) [sonar-pmd-plugin-2.8.jar:na] at org.sonar.batch.phases.SensorsExecutor.execute(SensorsExecutor.java:58) [sonar-batch-2.8.jar:na] at org.sonar.batch.phases.Phases.execute(Phases.java:80) [sonar-batch-2.8.jar:na] at org.sonar.batch.ProjectBatch.execute(ProjectBatch.java:59) [sonar-batch-2.8.jar:na] at org.sonar.batch.Batch.analyzeModule(Batch.java:164) [sonar-batch-2.8.jar:na] at org.sonar.batch.Batch.analyzeModules(Batch.java:82) [sonar-batch-2.8.jar:na] at org.sonar.batch.Batch.execute(Batch.java:62) [sonar-batch-2.8.jar:na] at org.sonar.runner.Launcher.executeBatch(Launcher.java:60) [sonar-runner.jar:na] at org.sonar.runner.Launcher.execute(Launcher.java:53) [sonar-runner.jar:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [na:1.6.0_23] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [na:1.6.0_23] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [na:1.6.0_23] at java.lang.reflect.Method.invoke(Method.java:597) [na:1.6.0_23] at org.sonar.runner.Main.delegateExecution(Main.java:111) [sonar-runner.jar:na] at org.sonar.runner.Main.execute(Main.java:67) [sonar-runner.jar:na] at org.sonar.runner.Main.main(Main.java:48) [sonar-runner.jar:na]
The resolution to the above error is to specify java source and target versions using the advanced parameters named sonar.java.source and sonar.java.target. If you are analyzing using sonar-running you need to specify these properties in the sonar-project.properties file.
Installing Sonar With Oracle
Installing sonar (version 2.8) is fairly easy after following the installation guide. Below is one tip which you should consider when using oracle as the database for sonar installation.
The Oracle schema for sonar should be created with the below sql commands
CREATE USER sonar IDENTIFIED BY sonar; GRANT CREATE SESSION, CREATE TABLE, CREATE VIEW, CREATE SYNONYM, CREATE SEQUENCE, CREATE PROCEDURE, CREATE TRIGGER TO sonar; ALTER USER Sonar Quota 300M ON Users;
Before I discovered the above queries (thanks to this blog) I tried creating the schema using create user and grant all permissions sql queries. Starting the sonar server always failed with the below error
ActiveRecord::ActiveRecordError: ORA-00904: “ENABLED”: invalid identifier: INSERT INTO users (row_identifier, login_id, full_name, email, row_version, user_id, enabled, login, name, crypted_password, salt, created_at, updated_at, remember_token, remember_token_expires_at, id) VALUES(null, null, null, ”, null, null, 0, ‘admin’, ‘Administrator’, ‘fdf038c3d9a8f1a260c7fe3c6657e91dc46ca448′, ’43b15bc57d3bd82b408970c550c03fdd8f29d95e’, TIMESTAMP’2011-06-03 21:42:54′, TIMESTAMP’2011-06-03 21:42:54′, null, null, ?)
Spring ignores CGLib subclasses when detecting @Transactional
Starting with spring version 3.0.4, cglib sub-classes are ignored when the spring code analyzes a class for @Transactional annotations.
Below is the method from AbstractFallbackTransactionAttributeSource class which determines if the transaction attribute is present on the method invocation. If the transaction attribute is present spring wraps the class around a proxy.
private TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) { // Don't allow no-public methods as required. if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) { return null; } // Ignore CGLIB subclasses - introspect the actual user class. Class<?> userClass = ClassUtils.getUserClass(targetClass); // The method may be on an interface, but we need attributes from the target class. // If the target class is null, the method will be unchanged. Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass); // If we are dealing with method with generic parameters, find the original method. specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod); // First try is the method in the target class. TransactionAttribute txAtt = findTransactionAttribute(specificMethod); if (txAtt != null) { return txAtt; } // Second try is the transaction attribute on the target class. txAtt = findTransactionAttribute(specificMethod.getDeclaringClass()); if (txAtt != null) { return txAtt; } if (specificMethod != method) { // Fallback is to look at the original method. txAtt = findTransactionAttribute(method); if (txAtt != null) { return txAtt; } // Last fallback is the class of the original method. return findTransactionAttribute(method.getDeclaringClass()); } return null; }
I traced this out after I found that creation of the application context for my junit test cases failed with spring 3.0.4 jars but passed when spring 3.0.3 jars were used. My spring context xml file for the junit test cases looked similar to
<context:component-scan base-package="sample"> <context:exclude-filter type="regex" expression="sample.SomeService" /> </context:component-scan> <bean id = "entityBasePackages" class = "java.lang.String"> <constructor-arg value = "sample"/> </bean>
The junit testcase wanted to mock the class SomeService which contained @Transactional annotations hence it was excluded from the component scan.
@Service public class SomeService { @Transactional public void transactionalMethod() { System.out.println("Transactional Method"); //perform some database operations } }
When the test case was executed with spring 3.0.4 jars it failed with the below error
Caused by: java.lang.IllegalArgumentException: Can not set sample.SomeService field sample.MyService.someService to $Proxy26 at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146) at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150) at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:63) at java.lang.reflect.Field.set(Field.java:657) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:503) ... 43 more
The application context creation failed because spring ignored the cglib subclass which was created by EasyMock for SomeService class. Hence a JDK proxy over a CGlib proxy was created which lead to type cast failure as indicated from the error above.
The resolution to the above failure could be any of the two options below
1. Creating an interface for SomeService and replacing the class reference variable in MyService class. This would make the type cast succeed because the JDK proxy created by spring would now include the new interface in the list of proxy interfaces.
2. Remove the @Transactional annotations from the SomeService class so that spring does not create any proxies.