View Javadoc
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  
36  import fr.paris.lutece.portal.service.database.AppConnectionService;
37  import fr.paris.lutece.portal.service.init.StartUpService;
38  import fr.paris.lutece.portal.service.spring.SpringContextService;
39  import fr.paris.lutece.portal.service.util.AppPropertiesService;
40  import fr.paris.lutece.util.ReferenceItem;
41  import fr.paris.lutece.util.ReferenceList;
42  import fr.paris.lutece.util.jpa.JPAConstants;
43  import fr.paris.lutece.util.jpa.JPAPersistenceUnitPostProcessor;
44  import fr.paris.lutece.util.jpa.transaction.ChainedTransactionManager;
45  
46  import org.apache.commons.lang3.StringUtils;
47  import org.apache.logging.log4j.LogManager;
48  import org.apache.logging.log4j.Logger;
49  import org.springframework.orm.jpa.JpaDialect;
50  import org.springframework.orm.jpa.JpaTransactionManager;
51  import org.springframework.orm.jpa.JpaVendorAdapter;
52  import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
53  import org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager;
54  import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor;
55  
56  import org.springframework.transaction.PlatformTransactionManager;
57  
58  import java.util.ArrayList;
59  import java.util.HashMap;
60  import java.util.List;
61  import java.util.Map;
62  
63  import javax.persistence.EntityManagerFactory;
64  
65  import javax.sql.DataSource;
66  
67  /**
68   * JPAStartupService
69   */
70  public class JPAStartupService implements StartUpService
71  {
72      /** The name of the property used by the JPA provider to specify the dialect */
73      private static final String JPA_DIALECT_PROPERTY = "jpa.dialect.property";
74      private static Logger _log = LogManager.getLogger( JPAConstants.JPA_LOGGER );
75  
76      /**
77       * Initialize JPA objects (Datasource, Persistence Unit Manager, Entity Manager Factory, Transaction Manager) for each pool.
78       */
79      public void process( )
80      {
81          ReferenceListnceList.html#ReferenceList">ReferenceList list = new ReferenceList( );
82          AppConnectionService.getPoolList( list );
83  
84          Map<String, EntityManagerFactory> mapFactories = new HashMap<>( );
85          List<PlatformTransactionManager> listTransactionManagers = new ArrayList<>( );
86          _log.info( "JPA Startup Service : Initializing JPA objects ..." );
87  
88          String strDialectProperty = AppPropertiesService.getProperty( JPA_DIALECT_PROPERTY );
89  
90          for ( ReferenceItem poolItem : list )
91          {
92              String strPoolname = poolItem.getCode( );
93  
94              DataSource ds = AppConnectionService.getPoolManager( ).getDataSource( strPoolname );
95              _log.info( "JPA Startup Service : DataSource retrieved for pool : " + strPoolname );
96              _log.debug( "> DS : " + ds.toString( ) );
97  
98              DefaultPersistenceUnitManager pum = new DefaultPersistenceUnitManager( );
99              pum.setDefaultDataSource( ds );
100 
101             PersistenceUnitPostProcessor [ ] postProcessors = {
102                     new JPAPersistenceUnitPostProcessor( )
103             };
104             pum.setPersistenceUnitPostProcessors( postProcessors );
105 
106             pum.afterPropertiesSet( );
107 
108             _log.info( "JPA Startup Service : Persistence Unit Manager for pool : " + strPoolname );
109             _log.debug( "> PUM : " + pum.toString( ) );
110 
111             LocalContainerEntityManagerFactoryBean lcemfb = new LocalContainerEntityManagerFactoryBean( );
112             lcemfb.setDataSource( ds );
113             lcemfb.setPersistenceUnitManager( pum );
114             lcemfb.setPersistenceUnitName( "jpaLuteceUnit" );
115 
116             JpaDialect jpaDialect = SpringContextService.getBean( "jpaDialect" );
117             lcemfb.setJpaDialect( jpaDialect );
118 
119             Map mapJpaProperties = SpringContextService.getBean( "jpaPropertiesMap" );
120             lcemfb.setJpaPropertyMap( mapJpaProperties );
121 
122             String strDialect = AppPropertiesService.getProperty( poolItem.getName( ) + ".dialect" );
123 
124             // replace default dialect if <poolname>.dialect is specified
125             if ( StringUtils.isNotBlank( strDialect ) )
126             {
127                 mapJpaProperties.put( strDialectProperty, strDialect );
128             }
129 
130             _log.debug( "Using dialect " + mapJpaProperties.get( strDialectProperty ) + " for pool " + poolItem.getName( ) );
131 
132             JpaVendorAdapter jpaVendorAdapter = SpringContextService.getBean( "jpaVendorAdapter" );
133             lcemfb.setJpaVendorAdapter( jpaVendorAdapter );
134 
135             lcemfb.afterPropertiesSet( );
136 
137             EntityManagerFactory emf = lcemfb.getNativeEntityManagerFactory( );
138             _log.info( "JPA Startup Service : EntityManagerFactory created for pool : " + strPoolname );
139             _log.debug( "> EMF : " + emf.toString( ) );
140 
141             JpaTransactionManager tm = new JpaTransactionManager( );
142             tm.setEntityManagerFactory( emf );
143             tm.setJpaDialect( jpaDialect );
144             _log.debug( "> JpaDialect " + jpaDialect );
145             tm.afterPropertiesSet( );
146             _log.info( "JPA Startup Service : JPA TransactionManager created for pool : " + strPoolname );
147             _log.debug( "> TM : " + tm.toString( ) );
148 
149             mapFactories.put( strPoolname, emf );
150             listTransactionManagers.add( tm );
151         }
152 
153         EntityManagerService ems = SpringContextService.getBean( "entityManagerService" );
154         ems.setMapFactories( mapFactories );
155 
156         ChainedTransactionManager ctm = SpringContextService.getBean( "transactionManager" );
157         ctm.setTransactionManagers( listTransactionManagers );
158         _log.info( "JPA Startup Service : completed successfully" );
159     }
160 
161     /**
162      * {@inheritDoc }
163      * 
164      * @return the name
165      */
166     public String getName( )
167     {
168         return ( "JPA Startup Service" );
169     }
170 }