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.

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

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 (code>@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.

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

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:


    
    
    
    

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:


   
   
   
 

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


    

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í.