jsr338-experts@jpa-spec.java.net

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

From: Scott Marlow <smarlow_at_redhat.com>
Date: Fri, 07 Jun 2013 11:40:57 -0400

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();
>>>>
>>>>
>>
>>