Category Archives: Spring

Spring factory method

Today I am going to write about a small trick that I have used recently. Lets imagine following problem: we are using JPA (Hibernate) and Spring together.


<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
	<property name="persistenceUnitName" value="testPU" />
	<property name="dataSource" ref="dataSource" />
	<property name="jpaProperties">
		<props>
			<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
		</props>
	</property>
</bean>

It works nice, without any problem. But imagine that one day you need to access Hibernate statistics. To achieve this, you have to have access to the Hibernate session factory. But we have no session factory here, we are using the entity manager which hides session factory underneath. How to access it? The solution is simple, you can use factory method.


<!-- Publishing session factory to be able view statistics -->
<bean id="sessionFactory" factory-bean="entityManagerFactory" factory-method="getSessionFactory" />

By this simple code we say to Spring: Hey, just call the method getSessionFactory on the entityManagerFactory bean and store the result as a bean with name sessionFactory. Since we are using Hibernate as the JPA provider, entityManagerFactory is instance of HibernateEntityManagerFactory and by a chance it has getSessionFactory method. Now we have access to the session factory and we can use it however we like.

Note: If you wonder why the hell I have started to write in something that looks almost like English when apparently I do even more mistakes than in Czech, the answer is simple. I just need to practice my English (apart from that I want to be world famous, not just known in Czech Republic)

Testing with Spring 2.5

Besides other cool features, Spring 2.5 brought completely rewritten support for functional tests. Before this version, Spring had support for functional tests using JUnit 3 only. If you needed to use JUnit 4 or TestNG you just did not get any help from the framework

Now you can use brand new annotations and you are not constrained in your choice of testing framework any more. For complete information, please consult Spring reference, I will show only small subset of the new features. Let’s take a look on the first example.



01 @RunWith(SpringJUnit4ClassRunner.class)
02 @ContextConfiguration(locations="classpath:applicationContext.xml")
03 @Transactional
04 public class TestJpaClientDao {
05 
06   private static final long PERSONAL_NUM = 123L;
07   @Autowired
08   private ClientDao clientDao;
09   
10   @Test
11   public void testCreateClient()
12   {
13     Client client = new Client(PERSONAL_NUM);
14     client.setName("John Doe");
15     client.addAddress(new Address("Old st.","2a","Prague","120 00"));
16     client.addAccount(new Account("123-4560789"));
17     client.addAccount(new Account("888-8888888"));
18     clientDao.createClient(client);
19     
20     Client loadedClient = clientDao.loadClientWithPersonalNumber(PERSONAL_NUM);
21     assertSame(client, loadedClient);
22   }

Here we see normal class with some annotations. But it is not normal class, it is JUnit 4 test. By RunWith annotation we are extending usual JUnit test runner in order to enable Spring support. Then we have to define where application context XML file(s) are (@ContextConfiguration annotation). Now we can use Autowire annotations to have all necessary dependencies injected. If we use annotation Transactional we obtain similar behavior as when we were using old AbstractTransactionalSpringContextTests. It means:

  1. The application context is shared for all test methods (in all test classes). So all the stuff is initialized only once. If your test does some changes to the application context and it has to be therefore discarded, you can use DirtiesContext annotation.
  2. All test methods are run in transaction which is rolled back at the end of every test method. You can change this behavior by Rollback annotation or by TransactionConfiguration annotation.

The new Spring test support is great. I just miss one thing. Old test support classes gave me possibility to finish and start a transaction in the middle of the test method (by calling setComplete, finishTransaction and startNewTransaction). I agree, that you do not need such feature very often, but sometimes it is handy. I was not able to find something similar in the new support classes. Finally I found a solution but it is not so straightforward as the old one (If you know better one please inform me).

In the following example I am trying to test whether my DAO is fetching addresses of the client so I do not get LazyInit exception. In my test I need to store a client to the database, finish the transaction, then load the client from the DB in a new transaction and finally check if the addresses are accessible even when no transaction is active.



01   @Test
02   @NotTransactional
03   public void testCreateAndLoadInTwoTransactions()
04   {
05     final Client client = new Client(PERSONAL_NUM);
06     client.setName("John Doe");
07     client.addAddress(new Address("Old st.","2a","Prague","120 00"));
08     client.addAccount(new Account("123-4560789"));
09     client.addAccount(new Account("888-8888888"));
10     getTransactionTemplate().execute(new TransactionCallback(){
11       public Object doInTransaction(TransactionStatus status) {
12         return clientDao.createClient(client);
13       }
14       
15     });
16     Client loadedClient = (ClientgetTransactionTemplate().execute(new TransactionCallback(){
17       public Object doInTransaction(TransactionStatus status) {
18         return clientDao.loadClientWithPersonalNumber(PERSONAL_NUM);
19       }
20     });
21     assertEquals(2,loadedClient.getAccounts().size());
22     
23     //cleanup
24     getTransactionTemplate().execute(new TransactionCallback(){
25       public Object doInTransaction(TransactionStatus status) {
26         clientDao.deleteClient(client.getId());
27         return null;
28       }
29       
30     });
31     
32   }
33   private TransactionTemplate getTransactionTemplate() {
34     return new TransactionTemplate(transactionManager);
35   }

As you can see, I have marked the method as NonTransactional. Therefore, Spring does not create a transaction for me and I can manage my transaction programmatically. For example using Spring transaction template. And that’s it.

The source code can be downloaded from SVN repository here.

Note: If you wonder why the hell I have started to write in something that looks almost like English when apparently I do even more mistakes than in Czech, the answer is simple. I just need to practice my English (apart from that I want to be world famous, not just known in Czech Republic)

Je Spring pomalý?

Omlouvám se za ten senzační titulek, ale to víte, chci na tento blog nalákat co nejvíce lidí, pak tu začnu prodávat reklamu a bude ze mě boháč. No a abych vás neochudil i o nějaký ten obsah, opravdu budu dneska psát o výkonnosti Springu, z počátku obecně, na konci se i dozvíte, jak výrazně zvýšit rychlost některých aplikací ve Springu napsaných.

Na nápad, zamyslet se, nad tím, jestli je Spring pomalý mě přivedl jeden kolega. Tvrdil, že pro jeden projekt vybrali EJB 3, protože dělali měření a vyšlo jim, že Spring je pomalý. Takže jak to s tím je?
Samozřejmě, že to je nesmysl. Ani ne tak proto, že by byl Spring tak dokonalý. Je to tím, že Spring nic nedělá. Spring jenom věci spojuje a veškerou práci na někoho deleguje. Napadají mě jenom dvě oblasti, kde by teoreticky mohl Spring někoho zpomalovat. První je start aplikace, kdy startuje aplikační kontext, vytvářejí se proxy a injektují se závislosti. Z mých zkušeností start aplikačního kontextu probíhá velmi rychle i u rozsáhlých projektů (jenom kdyby nezdržoval ten Hibernate). Další oblastí, kde by teoreticky mohl Spring běh aplikace zpomalit je AOP. Ale i to z velké části deleguje na JRE nebo CGLIB. Skoro všechno ostatní neřeší Spring, ale jiné produkty (Hibernate, aplikační server, JDBC, Quartz, …). Takže zopakujme si to znovu. Spring nic nedělá, jenom nám spojuje kousky skládačky dohromady. Pokud je ta skládačka pomalá, nemůže za to lepidlo, můžou za to ty kousky samotné.

Na příklad uvedu poměrně častý důvod, proč jsou některé aplikace ve Springu pomalé. (Nečekejte žádný zázračný recept). Může za to tento kus konfigurace:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
	<property name="driverClassName" value="${jdbc.driverClassName}"/>
	<property name="url" value="${jdbc.url}"/>
	<property name="username" value="${jdbc.username}"/>
	<property name="password" value="${jdbc.password}"/>
</bean>

Objevuje se v ukázkových aplikacích dodávaných se Springem. Stává se, že si programátor nepřečte komentář v XML souboru nebo JavaDocu a tento DataSource použije i na produkci. Kdyby si ten komentář přečetl, zjistil by, že použitý DataSource slouží pouze pro testovací účely – není to žádný connection pool. Pro produkci by měla se použít nějaká knihovna, která se zabývá poolováním DB spojení, například DBCP:

<bean id=”dataSource” class=”org.apache.commons.dbcp.BasicDataSource” destroy-method=”close“>
   <property name="driverClassName" value="${jdbc.driverClassName}"/>
   <property name="url" value="${jdbc.url}"/>
   <property name="username" value="${jdbc.username}"/>
 <property name="password" value="${jdbc.password}"/>
</bean>

Ještě lépší je použít DataSource poskytnutý serverem

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="jdbc/myDataSource" />
</bean>

Takže až vám příště bude připadat, že je Spring pomalý, uvědomte si, že je chyba pravděpodobně někde jinde. Nejpravděpodobněji mezi klávesnicí a židlí.