JPAStartupService.java

  1. /*
  2.  * Copyright (c) 2002-2022, City of Paris
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  *  1. Redistributions of source code must retain the above copyright notice
  10.  *     and the following disclaimer.
  11.  *
  12.  *  2. Redistributions in binary form must reproduce the above copyright notice
  13.  *     and the following disclaimer in the documentation and/or other materials
  14.  *     provided with the distribution.
  15.  *
  16.  *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
  17.  *     contributors may be used to endorse or promote products derived from
  18.  *     this software without specific prior written permission.
  19.  *
  20.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23.  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  24.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  25.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  26.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  30.  * POSSIBILITY OF SUCH DAMAGE.
  31.  *
  32.  * License 1.0
  33.  */
  34. package fr.paris.lutece.portal.service.jpa;

  35. import fr.paris.lutece.portal.service.database.AppConnectionService;
  36. import fr.paris.lutece.portal.service.init.StartUpService;
  37. import fr.paris.lutece.portal.service.spring.SpringContextService;
  38. import fr.paris.lutece.portal.service.util.AppPropertiesService;
  39. import fr.paris.lutece.util.ReferenceItem;
  40. import fr.paris.lutece.util.ReferenceList;
  41. import fr.paris.lutece.util.jpa.JPAConstants;
  42. import fr.paris.lutece.util.jpa.JPAPersistenceUnitPostProcessor;
  43. import fr.paris.lutece.util.jpa.transaction.ChainedTransactionManager;

  44. import org.apache.commons.lang3.StringUtils;
  45. import org.apache.logging.log4j.LogManager;
  46. import org.apache.logging.log4j.Logger;
  47. import org.springframework.orm.jpa.JpaDialect;
  48. import org.springframework.orm.jpa.JpaTransactionManager;
  49. import org.springframework.orm.jpa.JpaVendorAdapter;
  50. import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
  51. import org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager;
  52. import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor;

  53. import org.springframework.transaction.PlatformTransactionManager;

  54. import java.util.ArrayList;
  55. import java.util.HashMap;
  56. import java.util.List;
  57. import java.util.Map;

  58. import javax.persistence.EntityManagerFactory;

  59. import javax.sql.DataSource;

  60. /**
  61.  * JPAStartupService
  62.  */
  63. public class JPAStartupService implements StartUpService
  64. {
  65.     /** The name of the property used by the JPA provider to specify the dialect */
  66.     private static final String JPA_DIALECT_PROPERTY = "jpa.dialect.property";
  67.     private static Logger _log = LogManager.getLogger( JPAConstants.JPA_LOGGER );

  68.     /**
  69.      * Initialize JPA objects (Datasource, Persistence Unit Manager, Entity Manager Factory, Transaction Manager) for each pool.
  70.      */
  71.     public void process( )
  72.     {
  73.         ReferenceList list = new ReferenceList( );
  74.         AppConnectionService.getPoolList( list );

  75.         Map<String, EntityManagerFactory> mapFactories = new HashMap<>( );
  76.         List<PlatformTransactionManager> listTransactionManagers = new ArrayList<>( );
  77.         _log.info( "JPA Startup Service : Initializing JPA objects ..." );

  78.         String strDialectProperty = AppPropertiesService.getProperty( JPA_DIALECT_PROPERTY );

  79.         for ( ReferenceItem poolItem : list )
  80.         {
  81.             String strPoolname = poolItem.getCode( );

  82.             DataSource ds = AppConnectionService.getPoolManager( ).getDataSource( strPoolname );
  83.             _log.info( "JPA Startup Service : DataSource retrieved for pool : " + strPoolname );
  84.             _log.debug( "> DS : " + ds.toString( ) );

  85.             DefaultPersistenceUnitManager pum = new DefaultPersistenceUnitManager( );
  86.             pum.setDefaultDataSource( ds );

  87.             PersistenceUnitPostProcessor [ ] postProcessors = {
  88.                     new JPAPersistenceUnitPostProcessor( )
  89.             };
  90.             pum.setPersistenceUnitPostProcessors( postProcessors );

  91.             pum.afterPropertiesSet( );

  92.             _log.info( "JPA Startup Service : Persistence Unit Manager for pool : " + strPoolname );
  93.             _log.debug( "> PUM : " + pum.toString( ) );

  94.             LocalContainerEntityManagerFactoryBean lcemfb = new LocalContainerEntityManagerFactoryBean( );
  95.             lcemfb.setDataSource( ds );
  96.             lcemfb.setPersistenceUnitManager( pum );
  97.             lcemfb.setPersistenceUnitName( "jpaLuteceUnit" );

  98.             JpaDialect jpaDialect = SpringContextService.getBean( "jpaDialect" );
  99.             lcemfb.setJpaDialect( jpaDialect );

  100.             Map mapJpaProperties = SpringContextService.getBean( "jpaPropertiesMap" );
  101.             lcemfb.setJpaPropertyMap( mapJpaProperties );

  102.             String strDialect = AppPropertiesService.getProperty( poolItem.getName( ) + ".dialect" );

  103.             // replace default dialect if <poolname>.dialect is specified
  104.             if ( StringUtils.isNotBlank( strDialect ) )
  105.             {
  106.                 mapJpaProperties.put( strDialectProperty, strDialect );
  107.             }

  108.             _log.debug( "Using dialect " + mapJpaProperties.get( strDialectProperty ) + " for pool " + poolItem.getName( ) );

  109.             JpaVendorAdapter jpaVendorAdapter = SpringContextService.getBean( "jpaVendorAdapter" );
  110.             lcemfb.setJpaVendorAdapter( jpaVendorAdapter );

  111.             lcemfb.afterPropertiesSet( );

  112.             EntityManagerFactory emf = lcemfb.getNativeEntityManagerFactory( );
  113.             _log.info( "JPA Startup Service : EntityManagerFactory created for pool : " + strPoolname );
  114.             _log.debug( "> EMF : " + emf.toString( ) );

  115.             JpaTransactionManager tm = new JpaTransactionManager( );
  116.             tm.setEntityManagerFactory( emf );
  117.             tm.setJpaDialect( jpaDialect );
  118.             _log.debug( "> JpaDialect " + jpaDialect );
  119.             tm.afterPropertiesSet( );
  120.             _log.info( "JPA Startup Service : JPA TransactionManager created for pool : " + strPoolname );
  121.             _log.debug( "> TM : " + tm.toString( ) );

  122.             mapFactories.put( strPoolname, emf );
  123.             listTransactionManagers.add( tm );
  124.         }

  125.         EntityManagerService ems = SpringContextService.getBean( "entityManagerService" );
  126.         ems.setMapFactories( mapFactories );

  127.         ChainedTransactionManager ctm = SpringContextService.getBean( "transactionManager" );
  128.         ctm.setTransactionManagers( listTransactionManagers );
  129.         _log.info( "JPA Startup Service : completed successfully" );
  130.     }

  131.     /**
  132.      * {@inheritDoc }
  133.      *
  134.      * @return the name
  135.      */
  136.     public String getName( )
  137.     {
  138.         return ( "JPA Startup Service" );
  139.     }
  140. }