users@jpa-spec.java.net

[jpa-spec users] [jsr338-experts] Re: two phase approach to creating the EMF, implicit CDI bean manager support ... was :schema generation proposed changes

From: Steve Ebersole <steve.ebersole_at_redhat.com>
Date: Mon, 17 Jun 2013 09:51:00 -0500

Why is adding a method "simpler"? "Simpler" in what sense? From a
user/integration perspective I don't think it makes any difference.
 From a provider perspective, I think the proposed solution is far more
conceptually correct and therefore simpler. And I think these
"conceptual" matches tend to work better from a user perspective as
well (when an API and the concept it tries to expose/model match up...).

I assume you mean adding preDeploy/preCreate to PersistenceProvider.
Here is what I mean about "conceptuality":

PersistenceProvider provider = ...;
provider.preDeploy( .. );
provider.createContainerEntityManagerFactory( .. );

How does the provider track the preDeploy call above as relative to the
eventual createContainerEntityManagerFactory call? Meaning, imagine:

PersistenceProvider provider = ...;
provider.preDeploy( setOfArgsForPU1 );
provider.preDeploy( setOfArgsForPU2 );
provider.createContainerEntityManagerFactory( pu1 );
provider.createContainerEntityManagerFactory( pu2 );

Unless we say that a PersistenceProvider instance needs to now
conceptually model a single "pu". But thats a different set of
assumptions than what we have today. A separate contract makes that
explicitly clear:

PersistenceProvider provider = ...;
Bootstrap boot1 = provider.getBootstrap( setOfArgsForPU1 );
Bootstrap boot2 = provider.getBootstrap( setOfArgsForPU2 );
boot1.createContainerEntityManagerFactory( pu1 );
boot2.createContainerEntityManagerFactory( pu2 );

There is also the fact that simply adding a method does not allow
opting in or opting out of this 2-phaseness. I guess that depends on
how and if this group decides to accept this proposal in general. And
if so, specifically, whether we expect all providers to provide a
2-phase bootstrap mechanism. Because if its not a requirement (aka,
its optional) then having an optional contract is the best way to
expose this period.

As an additional suggestion, in the Hibernate version of this I
actually added methods to "Bootstrap" to handle schema-generation as
well.


On Mon 17 Jun 2013 09:18:25 AM CDT, gordon yorke wrote:
> Having a two step deployment of the persistence unit is a good idea.
> It would be a lot simpler to add a single "preDeploy" or "preCreate"
> method to the current SPI though.
> --Gordon
>
> On 17/06/2013 10:56 AM, Scott Marlow wrote:
>> A few minor changes to the below proposed interfaces are here (they
>> just need a package change to javax.persistence :-)
>>
>> https://github.com/scottmarlow/jipijapa/commit/db861170076cc9dbc4c07b6fb2facb30c0bc0e8e#L3R30
>>
>>
>> +
>>
>> https://github.com/scottmarlow/jipijapa/commit/db861170076cc9dbc4c07b6fb2facb30c0bc0e8e#L2R27
>>
>>
>>
>> On 06/11/2013 10:18 AM, Scott Marlow wrote:
>>> I would like to introduce the least pain, when/if we switch to allowing
>>> a two phase bootstream of the container EMF. I propose that we
>>> introduce a TwoPhaseBootstrap interface, if the persistence provider
>>> implements the TwoPhaseBootstrap interface, the methods can be used by
>>> the caller (e.g. EE container looking to create the container entity
>>> manager factory).
>>>
>>> public interface TwoPhaseBootstrap {
>>> Bootstrap
>>> createContainerEntityManagerFactoryTwoPhase(PersistenceUnitInfo, Map);
>>> }
>>>
>>> public interface Bootstrap {
>>> EntityManagerFactory buildEntityManagerFactory();
>>> }
>>>
>>> IMO, this is a good way to allow full JPA support
>>> (ClassFileTransformers) and CDI implicit/explicit support (bean manager
>>> can be passed into the persistence provider). Without this change, I'm
>>> afraid that all deployments with EJB modules, will need to choose
>>> between ClassFileTransformers working or use of CDI with entity
>>> listeners (performance vs functionality).
>>>
>>> Does anyone agree or disagree with making a change like the above asap?
>>>
>>> Scott
>>>
>>> On 06/07/2013 11:40 AM, Scott Marlow wrote:
>>>> On 08/10/2012 07:35 PM, Linda DeMichiel wrote:
>>>>> Scott, Steve
>>>>>
>>>>> Thanks for the proposal.
>>>>>
>>>>> Folks, I'd like to get feedback from the group on this, particularly
>>>>> from container and
>>>>> persistence provider implementors.
>>>>>
>>>>> thanks,
>>>>>
>>>>> -Linda
>>>>>
>>>>>
>>>>> On 8/9/2012 10:50 AM, Scott Marlow wrote:
>>>>>> The idea of having a separate generateSchema() that might do the
>>>>>> same
>>>>>> work as would of been done in
>>>>>> createContainerEntityManagerFactory() (if certain properties are
>>>>>> specified), brings to mind some other recent
>>>>>> discussions (one that I raised about deployment ordering concerns).
>>>>>>
>>>>>> Could we add other methods that provide a two-step approach to
>>>>>> creating the container manager entity manager factory? EE
>>>>>> Containers will still need to handle older JPA providers but we
>>>>>> could
>>>>>> offer faster/more concurrent application
>>>>>> deployment for JPA 2.1 and greater.
>>>>>>
>>>>>> The reason for turning createContainerEntityManagerFactory(),
>>>>>> into two
>>>>>> phases, is to allow the EE container to control
>>>>>> when different JPA deployment operations can occur. More
>>>>>> specifically,
>>>>>> I would like to have control over when the
>>>>>> persistence provider performs the following aspects of
>>>>>> createContainerEntityManagerFactory():
>>>>
>>>> Perhaps we should start a new thread if there is more interest in
>>>> switching to a two phase approach to creating the container entity
>>>> manager factory (for post 2.1). I'm just now learning of a conflict
>>>> between implicit CDI bean manager support and using
>>>> ClassFileTransformers to enhance/rewrite entity classes. I'd like to
>>>> allow both but the features seem to conflict with each other.
>>>>
>>>> Knowing whether there is an explicit CDI bean manager, is easy to
>>>> detect
>>>> (beans.xml is found) but for the implicit support, we assume there
>>>> is a
>>>> bean manager if there is an EJB module. When we create the container
>>>> entity manager factory, if we pass in an implicit CDI bean manager,
>>>> the
>>>> CDI bean manager creation will scan application classes, which means
>>>> ClassFileTransformers will register to late.
>>>>
>>>> Thoughts?
>>>>
>>>>>>
>>>>>> - Scanning for annotations & adding class transformers (to ensure
>>>>>> that
>>>>>> this happens before other EE deployers load
>>>>>> application classes).
>>>>>>
>>>>>> - DataSource is used (this will help with use of
>>>>>> @DataSourceDefinition
>>>>>> which might not be initialized until after the
>>>>>> other EE deployers have at least started scanning application
>>>>>> classes
>>>>>> for @DataSourceDefinition).
>>>>>>
>>>>>> The following is from an extension that we (Steve & I) started to
>>>>>> work
>>>>>> on, to accomplish this:
>>>>>>
>>>>>> public interface PersistenceProvider {
>>>>>> // Transformers added during this call
>>>>>> Bootstrap getBootstrap(PersistenceUnitInfo, Map);
>>>>>> }
>>>>>>
>>>>>> public interface Bootstrap {
>>>>>> // datasources accessible during either of these calls
>>>>>> void manageSchema();
>>>>>> EntityManagerFactory buildEntityManagerFactory();
>>>>>> }
>>>>>>
>>>>>> Scott
>>>>>>
>>>>>> On 08/08/2012 01:17 PM, Linda DeMichiel wrote:
>>>>>>> Please let me know if there are any further comments on this, as I
>>>>>>> would otherwise like to proceed to fold it into the spec.
>>>>>>>
>>>>>>> thanks,
>>>>>>>
>>>>>>> -Linda
>>>>>>>
>>>>>>>
>>>>>>> On 7/23/2012 4:55 PM, Linda DeMichiel wrote:
>>>>>>>> Here's an updated version of my earlier schema generation
>>>>>>>> proposal,
>>>>>>>> broken out as to proposed spec changes. You should hopefully find
>>>>>>>> this considerably more flexible and detailed than the earlier
>>>>>>>> draft.
>>>>>>>>
>>>>>>>> -Linda
>>>>>>>>
>>>>>>>> ----------------------------
>>>>>>>>
>>>>>>>> Proposed spec changes:
>>>>>>>>
>>>>>>>>
>>>>>>>> New Section: Schema Generation [to follow section 9.3]
>>>>>>>>
>>>>>>>> Schema generation may either happen prior to application
>>>>>>>> deployment or
>>>>>>>> when the entity manager factory is created as part of the
>>>>>>>> application
>>>>>>>> deployment and initialization process.
>>>>>>>>
>>>>>>>> * In Java EE environments, the container may call the
>>>>>>>> PersistenceProvider generateSchema method separately from and/or
>>>>>>>> prior to the creation of the entity manager factory for the
>>>>>>>> persistence unit, or the container may pass additional
>>>>>>>> information to the createContainerEntityManagerFactory call to
>>>>>>>> cause schema generation to happen as part of the entity manager
>>>>>>>> factory creation and application initialization process. The
>>>>>>>> information passed to these methods determines whether the
>>>>>>>> generation of schemas and/or tables occurs directly in the target
>>>>>>>> database, or whether DDL scripts for schema generation are
>>>>>>>> created, or both.
>>>>>>>>
>>>>>>>> * In Java SE environments, the application may call the
>>>>>>>> Persistence
>>>>>>>> generateSchema method separately from and/or prior to the creation
>>>>>>>> of the entity manager factory or may pass information to the
>>>>>>>> createEntityManagerFactory method to cause schema generation to
>>>>>>>> occur as part of the entity manager factory creation.
>>>>>>>>
>>>>>>>>
>>>>>>>> The application may provide DDL scripts to be used for schema
>>>>>>>> generation, and package these scripts as part of the
>>>>>>>> persistence unit
>>>>>>>> or specify URLs corresponding to the location of such scripts. In
>>>>>>>> Java EE environments, such scripts may be executed by the
>>>>>>>> container,
>>>>>>>> or the container may direct the persistence provider to execute
>>>>>>>> the
>>>>>>>> scripts; in Java SE environments, the execution of the scripts
>>>>>>>> is the
>>>>>>>> responsibility of the persistence provider. In the absence of the
>>>>>>>> specification of scripts, schema generation, if requested, will be
>>>>>>>> determined by the object/relational metadata of the persistence
>>>>>>>> unit.
>>>>>>>>
>>>>>>>>
>>>>>>>> The following standard properties are defined for use in schema
>>>>>>>> generation. In Java EE environments these properties are passed by
>>>>>>>> the container in the Map argument to the PersistenceProvider
>>>>>>>> generateSchema method or createContainerEntityManagerFactory
>>>>>>>> method.
>>>>>>>> In Java SE environments, they are passed in the Map argument to
>>>>>>>> the
>>>>>>>> Persistence generateSchema or createEntityManagerFactory method.
>>>>>>>>
>>>>>>>>
>>>>>>>> javax.persistence.schema-generation-target:
>>>>>>>>
>>>>>>>> The schema-generation-target property specifies whether the schema
>>>>>>>> is to be created in the database, whether scripts are to be
>>>>>>>> generated, or both.
>>>>>>>>
>>>>>>>> values for this property: DATABASE, SCRIPTS, DATABASE_AND_SCRIPTS
>>>>>>>> [Open Issue: introduce for these enum or use strings? Better
>>>>>>>> names??]
>>>>>>>>
>>>>>>>>
>>>>>>>> javax.persistence.schema-generation-action:
>>>>>>>>
>>>>>>>> The schema-generation-action property is used to specify the
>>>>>>>> action
>>>>>>>> to be taken by the persistence provider. If the
>>>>>>>> schema-generation-target property is not specified, no action must
>>>>>>>> be taken.
>>>>>>>>
>>>>>>>> values for this property: NONE, CREATE, DROP_AND_CREATE, DROP
>>>>>>>> [Open Issue: enum strings ("none", "create",
>>>>>>>> "drop-and-create",...)
>>>>>>>>
>>>>>>>>
>>>>>>>> javax.persistence.create-database-schemas
>>>>>>>>
>>>>>>>> In Java EE environments, it is anticipated that the Java EE
>>>>>>>> platform provider may wish to control the creation of database
>>>>>>>> schemas rather than delegate this task to the persistence
>>>>>>>> provider.
>>>>>>>> The create-database-schemas property specifies whether the
>>>>>>>> persistence provider is to create the database schema(s) in
>>>>>>>> addition to creating database objects such as tables, sequences,
>>>>>>>> constraints, etc. The value of this boolean property should be set
>>>>>>>> to true if the persistence provider is to create schemas in the
>>>>>>>> database or to generate DDL which is to contain "CREATE SCHEMA"
>>>>>>>> commands. If this property is not supplied, the provider should
>>>>>>>> not attempt to create database schemas. This property may be
>>>>>>>> specified in Java SE environments as well.
>>>>>>>>
>>>>>>>>
>>>>>>>> javax.persistence.ddl-create-script-target,
>>>>>>>> javax.persistence.ddl-drop-script-target:
>>>>>>>>
>>>>>>>> If scripts are to be generated, the target locations for the
>>>>>>>> writing of these scripts must be specified. These targets may take
>>>>>>>> the form of either Writers or strings designating URLs. The
>>>>>>>> persistence provider must produce both create and drop scripts if
>>>>>>>> the corresponding DDL targets are specified. This is independent
>>>>>>>> of whether a drop action is included in the value passed for the
>>>>>>>> schema-generation-action property. If the schema-generation-target
>>>>>>>> property specifies scripts and script targets are not specified,
>>>>>>>> the IllegalArgumentException should be thrown by the provider.
>>>>>>>>
>>>>>>>> ddl-create-script-target: a Writer configured for the persistence
>>>>>>>> provider for output of the DDL script or a string specifying
>>>>>>>> the URL for the DDL script. This property should only be
>>>>>>>> specified if scripts are to be generated.
>>>>>>>>
>>>>>>>> ddl-drop-script-target: a Writer configured for the persistence
>>>>>>>> provider for output of the DDL script or a string specifying the
>>>>>>>> URL for the DDL script. This property should only be specified
>>>>>>>> if scripts are to be generated.
>>>>>>>> [Suggestions for better names ??]
>>>>>>>>
>>>>>>>>
>>>>>>>> javax.persistence.database-product-name,
>>>>>>>> javax.persistence.database-product-version,
>>>>>>>>
>>>>>>>> If scripts are to be generated by the persistence provider and a
>>>>>>>> connection to the target database is not supplied, the
>>>>>>>> javax.persistence.database-product-name property must be
>>>>>>>> specified. The value of this property should be the value
>>>>>>>> returned for the target database by the JDBC DatabaseMetaData
>>>>>>>> method getDatabaseProductName. If sufficient database version
>>>>>>>> information is not included in the result of this method, the
>>>>>>>> database-product-version property should also be specified, and
>>>>>>>> should contain the value returned by the JDBC
>>>>>>>> getDatabaseProductVersion method.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> javax.persistence.ddl-create-script-source,
>>>>>>>> javax.persistence.ddl-drop-script-source:
>>>>>>>>
>>>>>>>> The ddl-create-script-source and ddl-drop-script-source properties
>>>>>>>> are used for script execution. In Java EE container environments,
>>>>>>>> it is generally expected that the container will be responsible
>>>>>>>> for executing DDL scripts, although the container is permitted to
>>>>>>>> delegate this task to the persistence provider. If DDL scripts
>>>>>>>> are to be used in Java SE environments or if the Java EE container
>>>>>>>> delegates the execution of scripts to the persistence provider,
>>>>>>>> these properties must be specified. The script sources may take
>>>>>>>> the form of either Readers or strings designating URLs.
>>>>>>>>
>>>>>>>> ddl-create-script-source: a Reader configured for reading of the
>>>>>>>> DDL script or a string specifying the URL for the DDL script.
>>>>>>>>
>>>>>>>> ddl-drop-script-source: a Reader configured for reading of the DDL
>>>>>>>> script or a string specifying the URL for the DDL script.
>>>>>>>> [Suggestions for better names ??]
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> javax.persistence.sql-load-script-source:
>>>>>>>>
>>>>>>>> A data load script may be supplied as part of the persistence
>>>>>>>> unit. In Java EE container environments, it is generally expected
>>>>>>>> that the container will be responsible for executing data load
>>>>>>>> scripts, although the container is permitted to delegate this task
>>>>>>>> to the persistence provider. If a load script is to be used in
>>>>>>>> Java SE environments or if the Java EE container delegates the
>>>>>>>> execution of the load script to the persistence provider, this
>>>>>>>> property must be specified. The script source may take the form
>>>>>>>> of either a Reader or a string designating a URL.
>>>>>>>>
>>>>>>>> sql-load-script-source: a Reader configured for reading of the SQL
>>>>>>>> load script for database initialization or a string specifying
>>>>>>>> the URL for the script.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> javax.persistence.schema-generation-connection:
>>>>>>>>
>>>>>>>> JDBC connection to be used for schema generation. This is intended
>>>>>>>> for use in Java EE environments, where the platform provider may
>>>>>>>> want to control the database privileges that are available to the
>>>>>>>> persistence provider. This connection is provided by the
>>>>>>>> container,
>>>>>>>> and should be closed by the container when the schema generation
>>>>>>>> request or entity manager factory creation completes. The
>>>>>>>> connection provided must have credentials sufficient for the
>>>>>>>> persistence provider to carry out the requested actions. If this
>>>>>>>> property is not specified, the persistence provider should use the
>>>>>>>> DataSource that has otherwise been provided.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> 9.4.1 PersistenceProvider Interface:
>>>>>>>>
>>>>>>>> New method:
>>>>>>>>
>>>>>>>> /**
>>>>>>>> * Create database schemas and/or tables and/or create DDL
>>>>>>>> * scripts as determined by the supplied properties
>>>>>>>> *
>>>>>>>> * @param info metadata for use by the persistence provider
>>>>>>>> * @param map properties for schema generation; these
>>>>>>>> * may also contain provider-specific properties
>>>>>>>> * @throws PersistenceException if insufficient or inconsistent
>>>>>>>> * configuration information is provided or if schema
>>>>>>>> * generation otherwise fails.
>>>>>>>> */
>>>>>>>> public void generateSchema(PersistenceUnitInfo info, Map map)
>>>>>>>>
>>>>>>>>
>>>>>>>> 9.6 Persistence Class
>>>>>>>>
>>>>>>>> New method:
>>>>>>>>
>>>>>>>> /**
>>>>>>>> * Create database schemas and/or tables and/or create DDL
>>>>>>>> * scripts as determined by the supplied properties
>>>>>>>> *
>>>>>>>> * @param persistenceUnitName the name of the persistence unit
>>>>>>>> * @param map properties for schema generation; these may also
>>>>>>>> * contain provider-specific properties. The values of
>>>>>>>> * these properties override any values that may have been
>>>>>>>> * configured elsewhere.
>>>>>>>> * @throws PersistenceException if insufficient or inconsistent
>>>>>>>> * configuration information is provided or if schema
>>>>>>>> * generation otherwise fails.
>>>>>>>> */
>>>>>>>> public void generateSchema(String persistenceUnitName, Map
>>>>>>>> properties)
>>>>>>>>
>>>>>>>>
>>>>>>>> -----------------------
>>>>>>>>
>>>>>>>> Section 8.2.1 persistence.xml file
>>>>>>>>
>>>>>>>> To be added to section 8.2.1:
>>>>>>>>
>>>>>>>> Scripts for use in schema generation and bulk loading of data
>>>>>>>> may be
>>>>>>>> packaged as part of the persistence unit.
>>>>>>>>
>>>>>>>>
>>>>>>>> To be added to Section 8.2.1.9 (properties):
>>>>>>>>
>>>>>>>> Scripts for use in schema generation are specified using the
>>>>>>>> ddl-create-script and ddl-drop-script elements. A script to
>>>>>>>> specify
>>>>>>>> SQL for the bulk loading of data may be specified by the
>>>>>>>> sql-load-script element. These scripts may be packaged as part
>>>>>>>> of the
>>>>>>>> persistence unit or designated by URL strings.
>>>>>>>>
>>>>>>>> <xsd:element name="database-scripts" type="database-scripts-type"
>>>>>>>> minOccurs="0"/>
>>>>>>>>
>>>>>>>> <xsd:complexType name="database-scripts-type">
>>>>>>>> <xsd:sequence>
>>>>>>>> <xsd:element name="ddl-create-script" type="xsd:string"/>
>>>>>>>> <xsd:element name="ddl-drop-script" type="xsd:string"
>>>>>>>> minOccurs="0"/>
>>>>>>>> <xsd:element name="sql-load-script" type="xsd:string"
>>>>>>>> minOccurs="0"/>
>>>>>>>> </xsd:sequence>
>>>>>>>> </xsd:complexType>
>>>>>>>>
>>>>>>>> [Open Issue: do we want to require a drop-script if a
>>>>>>>> create-script
>>>>>>>> has been provided?]
>>>>>>>>
>>>>>>>> -----------
>>>>>>>>
>>>>>>>> Chapter 11:
>>>>>>>>
>>>>>>>> New annotations for use in schema generation:
>>>>>>>>
>>>>>>>> @Target({}) @Retention(RUNTIME)
>>>>>>>> public @interface Index {
>>>>>>>> String name() default "";
>>>>>>>> String columnList();
>>>>>>>> boolean unique() default false; // should this be here or just use
>>>>>>>> UniqueConstraints?
>>>>>>>> }
>>>>>>>>
>>>>>>>> columnList syntax follows that of the OrderBy annotation:
>>>>>>>>
>>>>>>>> columnList::= indexColumn [, indexColumn]*
>>>>>>>> indexColumn::= columnName [ASC | DESC]
>>>>>>>>
>>>>>>>> If ASC or DESC is not specified, ASC is assumed
>>>>>>>>
>>>>>>>> Index[] indexes() default {};
>>>>>>>> is to be added to Table, SecondaryTable, CollectionTable,
>>>>>>>> JoinTable,
>>>>>>>> and TableGenerator
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> /**
>>>>>>>> * Provides for defining a foreign key constraint or for overriding
>>>>>>>> * or disabling the persistence provider's default foreign key
>>>>>>>> * definition.
>>>>>>>> */
>>>>>>>> @Target({}) @Retention(RUNTIME)
>>>>>>>> public @interface ForeignKey {
>>>>>>>> String name() default "";
>>>>>>>> String foreignKeyDefinition() default "";
>>>>>>>> boolean disableForeignKey() default false;
>>>>>>>> }
>>>>>>>>
>>>>>>>>
>>>>>>>> The syntax used in the foreignKeyDefinition element should
>>>>>>>> follow the
>>>>>>>> SQL syntax used by the target database for foreign key
>>>>>>>> constraints.
>>>>>>>> E.g., this would likely be similar to the following:
>>>>>>>>
>>>>>>>> FOREIGN KEY ( <COLUMN expression> {, <COLUMN expression>}... )
>>>>>>>> REFERENCES <TABLE identifier> [ ( <COLUMN expression> {, <COLUMN
>>>>>>>> expression>}... ) ]
>>>>>>>> [ ON UPDATE <referential action> ]
>>>>>>>> [ ON DELETE <referential action> ]
>>>>>>>>
>>>>>>>> If disableForeignKey is specified as true, the provider must not
>>>>>>>> generate
>>>>>>>> a foreign key constraint.
>>>>>>>>
>>>>>>>>
>>>>>>>> The following is to be added to JoinColumn, JoinColumns,
>>>>>>>> MapKeyJoinColumn,
>>>>>>>> MapKeyJoinColumns, PrimaryKeyJoinColumn and PrimaryKeyJoinColumns:
>>>>>>>>
>>>>>>>> ForeignKey foreignKey() default @ForeignKey();
>>>>>>>>
>>>>>>>>
>>>>>>
>>>>>>
>>>>
>>>
>>
>