This tutorial shall provide a first step to create an OData V4 service based on JPA metadata. It builds the foundation for the upcoming once.
Eclipse is used as IDE, but another IDE could be used as well. The IDE should contain Spring support like the Eclipse Plug-in Spring Tools 4.
In order to follow this tutorial, you should have
-
Basic knowledge about OData and OData V4
-
Knowledge of the Java programming language
-
Basic knowledge about building with Maven
-
Optional: knowledge about Spring
In order to perform the tutorial you need:
-
A Java JDK 17 or higher
-
A Eclipse IDE for Java EE, or another one that provides the same functionality
-
Optional: Maven separately installed, to perform Maven commands in case the JPA Processor projects should not be imported into your IDE
-
Optional: Git separately installed.
We start by cloning the repository. This can be done either via git clone https://github.com/SAP/olingo-jpa-processor-v4
or by using your IDE:
Open a shell, like the Windows console, navigate to the directory the repository had been cloned to and then to odata-jpa-archetype-spring
. Starting from the home directory this could be e.g. cd git\olingo-jpa-processor-v4\jpa-archetype\odata-jpa-archetype-spring
. We do that to generate the archetype. This is done by execute mvn clean install archetype:update-local-catalog
. Alternatively you can also use your IDE:
In your .m2 directory there should be a file called archetype-catalog.xml
:
This should contain the information about archetype:
<archetype-catalog xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-catalog/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-catalog/1.0.0 http://maven.apache.org/xsd/archetype-catalog-1.0.0.xsd">
<archetypes>
<archetype>
<groupId>com.sap.olingo</groupId>
<artifactId>odata-jpa-archetype-spring</artifactId>
<version>2.3.1</version>
</archetype>
</archetypes>
</archetype-catalog>
Now that we have generated the archetype, we can create a maven project. In Eclipse we can do so by performing the following steps. Choose File → New → Others and select Maven Project:
Then we have to choose the workspace. Choose Use default Workspace location:
Next choose the archetype odata-jpa-archetype-spring. You can use com.sap.olingo as filter:
As a last step some parameter have to be provided:
Parameter Name | Value |
---|---|
Group Id |
com.example |
Artifact Id |
trippin |
punit |
Trippin |
schema |
Trippin |
entity-table |
Person |
value-object-table |
Trip |
After Finish was pressed a project gets created:
-
The project contains already some integration tests, which we can execute. The test base on [REST Assured](https://github.com/rest-assured/). They are located under
src/test/java
in packagecom.exmple.trippin.integrationtest
. Right click on the project: Run As → JUnit Test. -
The service can be started. Right click on the project: Run As → Spring Boot App. In the favoured browser you should be able to execute e.g. one of the following requests:
-
We can create entities either using
curl
command or a rest tool like Apache JMeter™, Postman or a browser plugin.-
Curl:
curl -X POST http://localhost:9010/Trippin/v1/Persons -H "Content-Type:application/json" -d "{\"Data\" : \"Hallo Welt\"}"
-
Rest tool:
URL: http://localhost:9010/Trippin/v1/Persons
Header: Content-Type:application/json
{ "Data " : "Hallo Welt "}
-
The result can be checked the by executing http://localhost:9010/Trippin/v1/Persons?$format=json
Looking at the pom.xml
file we see that the latest version (which is available when the tutorial was written) of
H2 Database shall be used, which requires a later version of
Flyway as well.
To use the JPA Processor the following dependency is all that is required:
<dependency>
<groupId>com.sap.olingo</groupId>
<artifactId>odata-jpa-processor</artifactId>
<version>${processor.version}</version>
</dependency>
-
odata-jpa-processor comes with a dependency to odata-jpa-metadata. The later one is responsible to convert the JPA annotations into OData metadata. The first one provides the necessary code to handle data requests like queries or changes. odata-jpa-metadata can be used stand alone, if the request handling should be done differently.
The other JPA Processor dependencies are optional:
-
odata-jpa-spring-support contains a small set of parameter to be used in the Spring
application.yml
. -
odata-jpa-processor-cb contains an enhancement of JPAs Criteria Builder interface, which allows the JPA Processor to use window function ROW_NUMBER and LIMIT/OFFSET in sub queries. Two things have to be pointed out:
-
This part is still in a beta state.
-
Not all databases support ROW_NUMBER with OVER (PARTITION BY …)
-
JPA Processor need to be customized to work properly. Package com.example.trippin.config
contains two classes that provide this information. The first is EclipseLinkJpaConfiguration
,
which is needed to make use of Eclipselink. For our service the most important part is in method entityManagerFactory
. Here we provide with .packages(EntityTemplate.class)
a reference to a package that contains the JPA entities and so defines our persistence-unit.
The second one is ProcessorConfiguration
. It has two methods. The first one creates a service context, which should be valid for the live time of the service:
@Bean
public JPAODataSessionContextAccess sessionContext(@Autowired final EntityManagerFactory emf)
throws ODataException {
return JPAODataServiceContext.with()
.setPUnit(punit) //(1)
.setEntityManagerFactory(emf)
.setTypePackage(rootPackages) //(2)
.setRequestMappingPath("Trippin/v1") //(3)
.build();
}
-
With punit, the persistence-unit name, we define the Namespace of the service.
-
The same source has the name of the rootPackage, which is needed once we want to build Java based Functions and Actions.
-
The RequestMappingPath is needed by Olingo in case a service uses Spring.
Note
|
The namepsace can be found in the metadata, after executing http://localhost:9010/Trippin/v1/$metadata: <edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
<edmx:DataServices>
<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Trippin">
...
<Schema>
</edmx:DataServices>
</edmx:Edmx> |
Note
|
The persistence-unit name is injected from the |
The second one is the creation of a request context, which is created for each request:
@Bean
@Scope(scopeName = SCOPE_REQUEST)
public JPAODataRequestContext requestContext() {
return JPAODataRequestContext.with()
.setCUDRequestHandler(new JPAExampleCUDRequestHandler()) //(1)
.setDebugSupport(new DefaultDebugSupport()) //(2)
.build();
}
In the beginning of a service development two instances are provided:
-
For each request that shall process changing requests an instance of a sub-class of
JPAAbstractCUDRequestHandler
must be provided. The project uses a generic implementationJPAExampleCUDRequestHandler
, which is handy during prototyping and model development, but was not created with the intend of productive usage, especially as this is the place to implement business logic. -
Olingo grants some insights into the request processing with the so called Debug Support. The JPA Process supports this as well. As our service shall provide the debug information, an instance of
DefaultDebugSupport
is provided. The debug information can be retrieved by addingodata-debug=html
orodata-debug=json
to the query. E.g.: http://localhost:9010/Trippin/v1/Persons?odata-debug=html
The Spring controller implementation in com.example.trippin.controller is simple. It just creates a JPAODataRequestHandler
instance and triggers the processing.
@RequestMapping(value = "**", method = { RequestMethod.GET, RequestMethod.PATCH,
RequestMethod.POST, RequestMethod.DELETE })
public void crud(final HttpServletRequest req, final HttpServletResponse resp) throws ODataException {
new JPAODataRequestHandler(serviceContext, requestContext).process(req, resp);
}
To learn more about the options the JPA Processor provides a growing set of tutorials is provided.
In addition, a set of previous tutorials exist: old tutorials. Even so they are not always up to date, they can be helpful.