Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve integration doc #9322

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,15 @@ What's interesting is the `ServiceRegistry` and the pluggable swapping of the di
The basic requirement for a `Service` is to implement the marker interface `org.hibernate.service.Service`.
Hibernate uses this internally for some basic type safety.

The `Service` can also implement a number of optional life-cycle related contracts:
The `Service` can also implement a number of optional lifecycle related contracts:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change this to maintain consistency. lifecycle is used elsewhere


`org.hibernate.service.spi.Startable`::
allows the `Service` impl to be notified that it is being started and about to be put into use.
`org.hibernate.service.spi.Stoppable`::
allows the `Service` impl to be notified that it is being stopped and will be removed from use.
`org.hibernate.service.spi.ServiceRegistryAwareService`::
allows the `Service` to be injected with a reference to the registry that is managing it. See <<services-dependencies>> for more details.
`org.hibernate.service.spi.Manageable`::
marks the `Service` as manageable in JMX provided the JMX integration is enabled. This feature is still incomplete.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The above stuff has been absent from the codebase

Other::
`Other`::
The different registry implementations also understand additional optional contracts specific to that registry. For details, see the details for each registry in <<services-registry>>.

[[services-dependencies]]
Expand All @@ -58,10 +56,10 @@ Services are allowed to declare dependencies on other services using either of t
Any method on the `Service` implementation class accepting a single parameter and annotated with `@InjectService` is considered requesting injection of another service.
+
By default, the type of the method parameter is expected to be the `Service` role to be injected.
If the parameter type is different than the `Service` role, the serviceRole attribute of the `@InjectService` annotation should be used to explicitly name the role.
If the parameter type is different than the `Service` role, the `serviceRole` attribute of the `@InjectService` annotation should be used to explicitly name the role.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If the parameter type is different than the `Service` role, the `serviceRole` attribute of the `@InjectService` annotation should be used to explicitly name the role.
If the parameter type is different to the `Service` role, the `serviceRole` attribute of the `@InjectService` annotation should be used to explicitly name the role.

+
By default, injected services are considered required, that is the start up will fail if a named dependent `Service` is missing.
If the `Service` to be injected is optional, the required attribute of the `@InjectService` annotation should be declared as `false` (default is `true`).
By default, injected services are considered required, that is the startup will fail if a named dependent `Service` is missing.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
By default, injected services are considered required, that is the startup will fail if a named dependent `Service` is missing.
By default, injected services are considered required, that is, the startup will fail if a named dependent `Service` is missing.

If the `Service` to be injected is optional, the `required` attribute of the `@InjectService` annotation should be declared as `false` (default is `true`).

`org.hibernate.service.spi.ServiceRegistryAwareService`::
+
Expand Down Expand Up @@ -103,7 +101,7 @@ Services in one registry can depend on and utilize services in that same registr
=== ServiceBinding

The association of a given `Service` to a given `ServiceRegistry` is called a binding and is represented by the `org.hibernate.service.spi.ServiceBinding` interface.
Furthermore, the specific contract between a ServiceBinding and the `ServiceRegistry` is represented by the `org.hibernate.service.spi.ServiceBinding.ServiceLifecycleOwner` interface.
Furthermore, the specific contract between a `ServiceBinding` and the `ServiceRegistry` is represented by the `org.hibernate.service.spi.ServiceBinding.ServiceLifecycleOwner` interface.

There are two ways a `Service` becomes associated (bound) to a `ServiceRegistry`.

Expand All @@ -118,12 +116,12 @@ Each specific type of registry defines its own `ServiceInitiator` specialization
=== Types of ServiceRegistries

Currently Hibernate utilizes three different `ServiceRegistry` implementations forming a hierarchy.
Each type is a specialization for the purpose of type-safety, but they add no new functionality.
Each type is a specialization for the purpose of type safety, but they add no new functionality.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for consistency reason. type safety is used more often elsewhere.


[[services-registry-boot]]
==== `BootstrapServiceRegistry`

The `org.hibernate.boot.registry.BootstrapServiceRegistry` holds three `Service` and is normally built by means of the `org.hibernate.boot.registry.BootstrapServiceRegistryBuilder` factory class.
The `org.hibernate.boot.registry.BootstrapServiceRegistry` holds three `Services` and is normally built by means of the `org.hibernate.boot.registry.BootstrapServiceRegistryBuilder` factory class.
The builder gives type safe access to customizing these three `Services`.

[IMPORTANT]
Expand All @@ -147,13 +145,13 @@ And just as important, it does so in a centralized, swappable manner.
The specific capabilities exposed on this `Service` include:

* Locating `Class` references by name. This includes application classes as well as _integration_ classes.
* Locating resources (properties files, xml files, etc) as _classpath resources_
* Interacting with `java.util.ServiceLoader`, Java's own `Service` provider discovery mechanism
* Locating resources (properties files, xml files, etc.) as _classpath resources_.
* Interacting with `java.util.ServiceLoader`, Java's own `Service` provider discovery mechanism.

===== `IntegratorService`

The `Service` role for this `Service` is `org.hibernate.integrator.spi.IntegratorService.`
Applications, third-party integrators and others all need to integrate with Hibernate. Historically this used to require something (usually the application) to coordinate registering the pieces of each integration needed on behalf of each integration. The `org.hibernate.integrator.spi.Integrator` contract formalized this "integration SPI". The IntegratorService manages all known integrators.
Applications, third-party integrators and others all need to integrate with Hibernate. Historically this used to require something (usually the application) to coordinate registering the pieces of each integration needed on behalf of each integration. The `org.hibernate.integrator.spi.Integrator` contract formalized this "integration SPI". The `IntegratorService` manages all known integrators.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Applications, third-party integrators and others all need to integrate with Hibernate. Historically this used to require something (usually the application) to coordinate registering the pieces of each integration needed on behalf of each integration. The `org.hibernate.integrator.spi.Integrator` contract formalized this "integration SPI". The `IntegratorService` manages all known integrators.
Applications, third-party integrators, and others all need to integrate with Hibernate. Historically this used to require something (usually the application) to coordinate registering the pieces of each integration needed on behalf of each integration. The `org.hibernate.integrator.spi.Integrator` contract formalized this "integration SPI". The `IntegratorService` manages all known integrators.

Oxford comma.


[TIP]
====
Expand All @@ -162,7 +160,7 @@ The concept of "Integrator" is still being actively defined and developed. Expec

There are two ways an integrator becomes known.

* The integrator may be manually registered by calling `BootstrapServiceRegistryBuilder#with(Integrator)`
* The integrator may be manually registered by calling `BootstrapServiceRegistryBuilder#with(Integrator)`.
* The integrator may be discovered, leveraging the standard Java `ServiceLoader` capability provided by the `ClassLoaderService`.
`Integrators` would simply define a file named `/META-INF/services/org.hibernate.integrator.spi.Integrator` and make it available on the classpath.
`ServiceLoader` covers the format of this file in detail, but essentially it lists classes by fully-qualified name that implement `Integrator` one per line.
Expand Down Expand Up @@ -191,9 +189,9 @@ This registry is generally built using the `org.hibernate.boot.registry.Standard
By default, it holds most of the `Services` used by Hibernate.
For the full list of `Services` typically held in the `StandardServiceRegistry`, see the source code of `org.hibernate.service.StandardServiceInitiators`.

In normal usage, the parent of the StandardServiceRegistry is the BootstrapServiceRegistry.
In normal usage, the parent of the `StandardServiceRegistry` is the `BootstrapServiceRegistry`.

The services of the StandardServiceRegistry can be extended (added to) and overridden (replaced).
The services of the `StandardServiceRegistry` can be extended (added to) and overridden (replaced).

===== `ConnectionProvider/MultiTenantConnectionProvider`

Expand All @@ -211,7 +209,7 @@ Comes in two distinct (and mutually exclusive) roles:

===== `TransactionCoordinatorBuilder`

`org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder` is used by Hibernate to integrate with and underlying transaction system.
`org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder` is used by Hibernate to integrate with an underlying transaction system.
It is responsible for building `org.hibernate.resource.transaction.spi.TransactionCoordinator` instances for use by each Hibernate `Session`.

===== `JtaPlatform`
Expand All @@ -229,7 +227,7 @@ The `org.hibernate.cache.spi.RegionFactory` `Service` defines the integration wi

===== `SessionFactoryServiceRegistryFactory`

`org.hibernate.service.spi.SessionFactoryServiceRegistryFactory` is a `Service` that acts as a factory for building the third type of `ServiceRegistry` (the SessionFactoryServiceRegistry) which we will discuss next.
`org.hibernate.service.spi.SessionFactoryServiceRegistryFactory` is a `Service` that acts as a factory for building the third type of `ServiceRegistry` (the `SessionFactoryServiceRegistry`) which we will discuss next.
I opted for the _factory as service_ approach because in the current design there is really not a good exposed hook-in spot for when the `SessionFactoryServiceRegistry` needs to be built.

[[services-registry-sf]]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
public interface EventPublishingService extends Service {

public void publish(Event theEvent);
void publish(Event theEvent);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we don't need to specify public for interface method

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ public class EventPublishingServiceContributor

@Override
public void contribute(StandardServiceRegistryBuilder builder) {
builder.addinitiator( eventpublishingserviceinitiator.instance );
builder.addInitiator( EventPublishingServiceInitiator.instance );

// if we wanted to allow other strategies (e.g. a jms
// queue publisher) we might also register short names
// queue publisher) we might also register short-names
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hyphenating "short names" is just weird. You don't need a hyphen between an adjective and a noun.

A hyphen would be used if this were a compound adjective, but it's not. So if there are other occurrences of "short-name", they should be fixed by removing the hyphen.

// here with the strategyselector. the initiator would
// then need to accept the strategy as a config setting
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ public void injectServices(ServiceRegistryImplementor serviceRegistry) {
this.serviceRegistry = serviceRegistry;
}

public void configure(Map configurationValues) {
this.jmsConnectionFactoryName = configurationValues
public void configure(Map<String, Object> configurationValues) {
this.jmsConnectionFactoryName = (String) configurationValues
.get( JMS_CONNECTION_FACTORY_NAME_SETTING );
this.destinationName = configurationValues
this.destinationName = (String) configurationValues
.get( JMS_DESTINATION_NAME_SETTING );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added generics usage as much as possible in this PR for using Map alone seems sloppy

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ public class EventPublishingServiceInitiator
"com.acme.EventPublishingService.enabled";

@Override
public Class<R> getServiceInitiated() {
public Class<EventPublishingService> getServiceInitiated() {
return EventPublishingService.class;
}

@Override
public R initiateService(
Map configurationValues,
public EventPublishingService initiateService(
Map<String, Object> configurationValues,
ServiceRegistryImplementor registry) {

final boolean enabled = extractBoolean(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import java.lang.Override;

public class LatestAndGreatestConnectionProviderImpl
implements ConnectionProvider, Startable, Stoppable, Configurable {

Expand All @@ -10,7 +8,7 @@ public class LatestAndGreatestConnectionProviderImpl
private boolean available = false;

@Override
public void configure(Map configurationValues) {
public void configure(Map<String, Object> configurationValues) {
// extract our config from the settings map
lagPoolBuilder = buildBuilder( configurationValues );
}
Expand All @@ -34,7 +32,7 @@ public void stop() {
@Override
public Connection getConnection() throws SQLException {
if ( !available ) {
throwException(
throw new HibernateException(
"LatestAndGreatest ConnectionProvider not available for use" )
}

Expand All @@ -45,7 +43,7 @@ public Connection getConnection() throws SQLException {
public void closeConnection(Connection conn) throws SQLException {
if ( !available ) {
warn(
"LatestAndGreatest ConnectionProvider not available for use" )
"LatestAndGreatestConnectionProvider not available for use" )
}

if ( conn == null ) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
public class LatestAndGreatestConnectionProviderImplContributor1
public class LatestAndGreatestConnectionProviderImplContributor
implements ServiceContributor {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Originally the example code snippets were prepared for two flavours:

  • LatestAndGreatestConnectionProviderImplContributor1
  • LatestAndGreatestConnectionProviderImplContributor2

one of the reasons is two meta-inf files were provided so using number suffix to differentiate between them:

  • ex2-meta-inf
  • ex3-meta-inf

However, the ex3-meta-inf was not used at all so it is deleted in this PR. Then it seems no such confusing suffix is needed.


@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
fully.qualified.package.LatestAndGreatestConnectionProviderImplContributor1
fully.qualified.package.LatestAndGreatestConnectionProviderImplContributor
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ public class LatestAndGreatestConnectionProviderImplContributor

@Override
public void contribute(
standardserviceregistrybuilder serviceregistrybuilder) {
StandardServiceRegistryBuilder serviceRegistryBuilder) {

// here we will register a short-name for our service strategy
strategyselector selector = serviceregistrybuilder
.getbootstrapserviceregistry().
.getservice( strategyselector.class );
StrategySelector selector = serviceRegistryBuilder
.getBootstrapServiceRegistry().
.getService( StrategySelector.class );

selector.registerstrategyimplementor(
connectionprovider.class,
"lag"
latestandgreatestconnectionproviderimpl.class
selector.registerStrategyImplementor(
ConnectionProvider.class,
"lag",
LatestAndGreatestConnectionProviderImpl.class
);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this code snippet is too sloppy

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably should be requireService() instead of getService() if we're being picky.

}

This file was deleted.

6 changes: 3 additions & 3 deletions documentation/src/main/asciidoc/integrationguide/preface.adoc
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[[preface]]
== Preface

Hibernate provides many integration points that allow integration new capabilities or supplying custom behavior for standard capabilities. This guide covers these integration points and is intended for software developers and architects who will be
Hibernate provides many integration points that allow integrating with new capabilities or supplying custom behavior for standard capabilities. This guide covers these integration points and is intended for software developers and architects who will be

- integrating Hibernate with Java EE application servers, Spring framework, caching solutions (e.g. Infinispan, Ehcache, Hazelcast).
- supplying custom integrations
- integrating Hibernate with Java EE application servers, Spring framework, caching solutions (e.g. Infinispan, Ehcache, Hazelcast),
- supplying custom integrations, or
- want to override standard capabilities