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

Feature/version 2.3.0 #414

Merged
merged 196 commits into from
Nov 21, 2024
Merged
Changes from all commits
Commits
Show all changes
196 commits
Select commit Hold shift + click to select a range
6200a5f
Feature/transient fields (#142)
wog48 Apr 14, 2020
2df7e8f
Add sonar plugin (#144)
wog48 Apr 15, 2020
dde6362
Feature/logging (#145)
wog48 Apr 18, 2020
78a8645
Feature/logging (#147)
wog48 May 3, 2020
7ab98ab
Feature/logging (#148)
wog48 May 4, 2020
8f32d18
Feature/logging (#150)
wog48 May 4, 2020
db7bd68
Feature/logging (#151)
wog48 May 5, 2020
86c5c4d
Feature/logging (#152)
wog48 May 7, 2020
5027b1f
Update README.md (#153)
wog48 May 8, 2020
fcde6c6
Feature/logging (#154)
wog48 May 8, 2020
66c76c0
Increase test coverage for criteria builder (#155)
wog48 May 9, 2020
c124d83
Feature/criteria builder (#156)
wog48 May 9, 2020
e3b5e59
Update README.md (#157)
wog48 May 9, 2020
d901965
Feature/criteria builder (#158)
wog48 May 12, 2020
1782881
Feature/criteria builder (#159)
wog48 May 17, 2020
bd6cfb5
Update README.md (#160)
wog48 May 19, 2020
fe7c443
Remove potential null pointer (#161)
wog48 May 21, 2020
54097b6
Bugfix/sonar issues (#162)
wog48 May 21, 2020
b933d49
Bugfix/sonar issues (#163)
wog48 May 21, 2020
440946c
Bugfix/sonar issues (#164)
wog48 May 23, 2020
a0aa728
Bugfix/sonar issues (#165)
wog48 May 23, 2020
cdb6b95
Feature/release 1.0.0 (#170)
wog48 May 26, 2020
1ca3554
Bugfix/issue98 (#173)
wog48 Jun 7, 2020
3473658
Bugfix/issue98 (#174)
wog48 Jun 20, 2020
3499dcb
sonar issues (#175)
wog48 Jun 20, 2020
353e0ff
Bugfix/issue98 (#176)
wog48 Jun 20, 2020
9fef01f
Bugfix/issue98 (#177)
wog48 Jun 20, 2020
d2a4288
Feature/criteria builder (#178)
wog48 Jun 21, 2020
b140624
Add README.md and correct spelling errors (#179)
wog48 Jun 21, 2020
5e29185
Feature/release 1.0.0 (#192)
wog48 Oct 16, 2020
8e42b89
Correct criteria builder implementation (#193)
wog48 Nov 4, 2020
df194e8
Feature/criteria builder (#194)
wog48 Nov 22, 2020
706b0e0
Feature/criteria builder (#195)
wog48 Nov 22, 2020
c92bd08
Feature/criteria builder (#196)
wog48 Nov 24, 2020
918cf9d
Feature/criteria builder (#197)
wog48 Nov 25, 2020
cb443ba
Feature/criteria builder (#198)
wog48 Nov 30, 2020
955dbd4
Feature/criteria builder (#199)
wog48 Dec 30, 2020
999e3b4
missing variable usage (#200)
wog48 Jan 3, 2021
febcbd3
Clean-up Sonar issues (#201)
wog48 Jan 3, 2021
b000c00
Bugfix/no mapper for operations (#202)
wog48 Jan 3, 2021
a254566
Feature/1.0.1 (#203)
wog48 Jan 3, 2021
df47af2
New version (#204)
wog48 Jan 4, 2021
1dfa42f
Bugfix/filter eq withdate (#205)
wog48 Jan 4, 2021
6d0c7e2
Us generated alias for column selection (#206)
wog48 Jan 4, 2021
a177795
Upgrade Version (#207)
wog48 Jan 4, 2021
47d669e
Reduce complexity (#209)
wog48 Jan 5, 2021
3bc5176
ALL did not work with functions like startswith (#210)
wog48 Jan 7, 2021
231f726
Update version (#208)
wog48 Jan 10, 2021
ac93dc5
Entity Set Path @ DB Functions (#211)
wog48 Jan 10, 2021
d27c6e6
Feature/new archetype (#212)
wog48 Jan 19, 2021
5504abd
Feature/new archetype (#213)
wog48 Jan 24, 2021
4419f0d
Feature/new archetype (#214)
wog48 Feb 10, 2021
d790102
Replace Reflections API by Reflections8 (#215)
wog48 Apr 21, 2021
8c1033c
Support entitytypes singeltons (#216)
wog48 May 17, 2021
77589e8
Update README.md (#218)
wog48 Oct 1, 2021
b2e5318
Solve issue 136 (#217)
wog48 Oct 3, 2021
c7b300b
Eliminate WhiteSource detected vulnerabilities (#219)
wog48 Oct 4, 2021
8c59937
Remove setExternalName from Metadata Post Processor (#220)
wog48 Oct 4, 2021
cbd6ac4
Support entitytypes singeltons (#221)
wog48 Oct 5, 2021
8d6f44f
Support entitytypes singeltons (#222)
wog48 Oct 7, 2021
6bdf79f
Query extension declaration (#223)
wog48 Nov 5, 2021
d53f7f6
Support entity types and singletons (#224)
wog48 Nov 7, 2021
545ce73
Support cast on navigations (#225)
wog48 Nov 10, 2021
d41ca35
Update README.md (#226)
wog48 Nov 11, 2021
f4fac3f
Bugfix/no constranis with ignored properties (#227)
wog48 Nov 13, 2021
8315f15
Bugfix/no constranis with ignored properties (#228)
wog48 Nov 15, 2021
7b0c8d3
Enable subtyping for complex types (#229)
wog48 Nov 17, 2021
06da7d4
Support transient properties that require ignored properties (#231)
wog48 Nov 20, 2021
0ff3ca1
Bugfix/multi level inheritance (#232)
wog48 Nov 24, 2021
d901476
Bugfix/multi level inheritance (#233)
wog48 Nov 27, 2021
2f56e13
Feature/release 1.0.3 (#234)
wog48 Nov 28, 2021
938b7a4
Feature/release 1.0.4 (#235)
wog48 Dec 7, 2021
c779a59
Feature/release 1.0.4 (#236)
wog48 Dec 10, 2021
38eb107
Error correction (#237)
wog48 Dec 17, 2021
47ee683
Feature/release 1.0.5 (#238)
wog48 Dec 17, 2021
134eceb
Update H2 version (#239)
wog48 Jan 10, 2022
e233a65
Feature/release 1.0.6 (#240)
wog48 Jan 10, 2022
8c669a1
Upgrade version and additional tests (#241)
wog48 Jan 25, 2022
37d9f27
New version an sonar clean-up (#242)
wog48 Jan 27, 2022
3338374
Release 1.1.0 (#243)
wog48 Jan 27, 2022
02b66ba
Release 1.1.0 (#244)
wog48 Jan 27, 2022
db4bcfc
Update version -> 1.0.8 (#245)
wog48 Mar 4, 2022
84cd240
Feature/release 1.0.0 (#247)
wog48 Jun 30, 2022
670d010
Generate metadata for overloaded action (#248)
wog48 Sep 4, 2022
2112bb4
Feature/action overload (#249)
wog48 Sep 7, 2022
79b6c56
Fix claims in collections where (#250)
wog48 Sep 7, 2022
be57eee
Use dbtype to build key pair in case a conversion exists (#251)
wog48 Sep 8, 2022
2325fd7
Enable more constructors for binding parameter (#252)
wog48 Sep 13, 2022
b95824f
Feature/more flexable constructor determination operations (#253)
wog48 Sep 14, 2022
214272b
New type cast added - they have possible data lost (#254)
wog48 Sep 16, 2022
0696ebc
Collection not longer retrieves transient (#255)
wog48 Sep 19, 2022
5d0713c
Enhance partner determination (#256)
wog48 Sep 19, 2022
0142d98
Bugfix/reuse navigation as partner (#257)
wog48 Sep 19, 2022
71bac32
Bugfix/reuse navigation as partner (#258)
wog48 Sep 20, 2022
a4b7dcf
No fallback to server locale in case bundle requested local not found…
wog48 Sep 27, 2022
e5ea988
Replace file reader (#260)
wog48 Sep 27, 2022
e693797
Replace fixed values by variables (#261)
wog48 Sep 27, 2022
cfdf322
Bugfix/error in controller test (#262)
wog48 Sep 28, 2022
2988b7a
Update archetype pom (#265)
wog48 Oct 10, 2022
3a9bd80
Defect/archetype pom (#266)
wog48 Oct 10, 2022
8eb51f3
Update test constants (#267)
wog48 Oct 11, 2022
6de32b1
Correct count behavior (#268)
wog48 Nov 3, 2022
734ec8f
Change to Java 11 (#269)
wog48 Nov 3, 2022
da93752
Update README.md (#270)
wog48 Nov 3, 2022
dd3ff96
Defect/count not working on hana (#271)
wog48 Nov 3, 2022
97f2208
Defect/java function parameter name (#272)
wog48 Nov 20, 2022
e488a46
Raise message in case of Void as return type for functions (#273)
wog48 Nov 21, 2022
2c3c4a6
Extension of visitor for java functions (#274)
wog48 Dec 4, 2022
96f2d50
Update version to 1.1.1 (#275)
wog48 Dec 14, 2022
10e1dec
Feature/predefined annotations (#276)
wog48 Dec 22, 2022
89deaae
Add page to order by builder (#277)
wog48 Dec 30, 2022
614b5ee
Feature/predefined annotations (#278)
wog48 Jan 15, 2023
11e6aad
Feature/predefined annotations (#279)
wog48 Jan 15, 2023
65d13c8
Feature/predefined annotations (#280)
wog48 Jan 15, 2023
56e9763
Update .xmake.cfg (#283)
wog48 Feb 12, 2023
8f6e3ff
Correct spelling (#281)
wog48 Feb 12, 2023
893d715
Feature/predefined annotations (#282)
wog48 Feb 18, 2023
af2b0f2
Update .xmake.cfg (#284)
wog48 Feb 20, 2023
ed3f488
Feature/predefined annotations (#286)
wog48 Apr 28, 2023
c0f0967
Feature/predefined annotations (#287)
wog48 May 13, 2023
dea342b
Clean-up pom and typo correction (#288)
wog48 May 24, 2023
29dd8d0
Solve issue 212 and fix permission check issue with join tables (#289)
wog48 Jun 10, 2023
6cb20b2
Fix issue, converting type (#290)
wog48 Jun 25, 2023
997a704
Multi step Mapped Superclass (#291)
wog48 Jun 25, 2023
e87c8c4
Upgrade H2 to 2.2.220 (#293)
wog48 Jul 10, 2023
05c8926
Correct navigation to one is null (#294)
wog48 Aug 6, 2023
176db5b
Fix join column determination with cyclic dependency (#295)
wog48 Aug 10, 2023
7fea8d2
Make OneToOne required and handle non JPA Processor errors in metadat…
wog48 Sep 3, 2023
7363173
Defect/issue214 (#297)
wog48 Sep 4, 2023
68a964f
Defect/issue214 (#298)
wog48 Sep 5, 2023
256c33d
Update .xmake.cfg (#300)
wog48 Sep 7, 2023
e3fa961
Update version to 2.0.0 (#299)
wog48 Oct 2, 2023
091b2b4
Defect/issue226 (#301)
wog48 Nov 11, 2023
005c85a
First level of COUNT query as IN (#302)
wog48 Nov 24, 2023
cf11992
Defect/issues239 (#303)
wog48 Nov 24, 2023
9fa771b
Defect/issues239 (#304)
wog48 Nov 27, 2023
7b8bc8f
Rename properties file to prevent name clashes (#305)
wog48 Nov 27, 2023
6b799c7
Clean-up pom and some code (#306)
wog48 Dec 3, 2023
30b7634
Defect/pom cleanup (#307)
wog48 Dec 3, 2023
c3f1307
Archetype and SOnar clean-up (#308)
wog48 Dec 5, 2023
0577fa8
Add protection where to collection query (#309)
wog48 Dec 5, 2023
93a4e79
Check if cast is necessary (#310)
wog48 Dec 6, 2023
5904b7c
Set version to 2.0.2 (#311)
wog48 Dec 6, 2023
128cf55
Update to Olingo 5.0.0 and remove wrapper (#314)
wog48 Dec 19, 2023
23b832a
Extend interface for server driven paging (#313)
wog48 Jan 7, 2024
229ee76
Feature/enhancement of paging (#315)
wog48 Jan 16, 2024
5bd45a6
First version and some clean-ups (#312)
wog48 Jan 16, 2024
22232b5
New query implementation for count (#316)
wog48 Jan 28, 2024
b67bc6f
Feature/annotation api extension (#317)
wog48 Jan 30, 2024
6dc289e
Update project files (#318)
wog48 Feb 7, 2024
819b7c0
Add null check for NOT IN clauses (#319)
wog48 Feb 9, 2024
28e752a
Fix $count problem with collection properties (#320)
wog48 Feb 17, 2024
ec54a08
Defect/use raw uri for vocabularies (#321)
wog48 Feb 27, 2024
9571aec
Defect/use raw uri for vocabularies (#322)
wog48 Feb 28, 2024
900096f
Defect/missing paging expand with cp (#323)
wog48 Mar 3, 2024
cd35566
Handle LIMIT and OFFSET with TypedQuery (#324)
wog48 Mar 25, 2024
91ebd6e
Defect/eclipse link hana problem (#325)
wog48 Mar 26, 2024
30ec04d
Check restrictions on IN clause (#326)
wog48 Apr 9, 2024
34d65ac
Correct NPE if enum property is nullable (#327)
wog48 Apr 16, 2024
38ae3d2
Update README.md (#328)
wog48 Apr 16, 2024
3513f0d
Fix duplicates result multi expands issue#292 (#329)
wog48 May 15, 2024
cc5a615
Defect/enumeration convertion error (#330)
wog48 May 17, 2024
9e0fb4b
Suppress generation of defaults for LIMIT and OFFSET (#331)
wog48 May 21, 2024
3e300cb
Enable order by to one associations (#333)
wog48 Jun 8, 2024
f1a2e29
Enhanced ETag handling for GET entity set requests (#332)
wog48 Jun 15, 2024
8d44a41
Defect/orderby navigation to on (#334)
wog48 Jun 16, 2024
45db05b
Correct collection property select clause issues (#335)
wog48 Jun 19, 2024
5e4df67
Enable nested lambda expressions (#336)
wog48 Jun 21, 2024
545adb6
Fix problem with expand and lambda to collection (#337)
wog48 Jun 21, 2024
c422895
Set version to 2.1.3 (#338)
wog48 Jun 23, 2024
6c00c37
Feature/release 2.1.3 (#339)
wog48 Jun 27, 2024
f3b6cad
Feature/release 2.1.3 (#340)
wog48 Jun 29, 2024
7cae220
Update to version 2.1.4 (#341)
wog48 Jun 30, 2024
1010db0
Update to version 2.2.0 (#342)
wog48 Jun 30, 2024
7aae7d6
Defect/issue 330 (#343)
wog48 Jun 30, 2024
4c3b74e
Defect/issue 330 (#344)
wog48 Jul 9, 2024
c7a8f00
Fix issue with orderby and description properties (#345)
wog48 Aug 5, 2024
1249108
server driven paging on expand (#346)
wog48 Sep 19, 2024
bc347b7
Update create response (#347)
wog48 Sep 22, 2024
31b2988
Feature/server driven paging expand (#348)
wog48 Sep 22, 2024
ed25d28
Feature/server driven paging expand (#349)
wog48 Oct 6, 2024
9054f6f
Update pom (#350)
wog48 Oct 17, 2024
e3aeafd
Update version to 2.3.0 (#351)
wog48 Oct 17, 2024
2a88f7a
Update version to 2.3.0-SNAPSHOT
wog48 Oct 18, 2024
c74a71b
Feature/add criteria update (#352)
wog48 Oct 26, 2024
1767b53
Change implementation of filter on boundary (#353)
wog48 Oct 27, 2024
ebc7e49
Merge remote-tracking branch 'jpa-processor/master' into
wog48 Oct 28, 2024
a02977f
Defect/issue 397 (#354)
wog48 Oct 29, 2024
3a27114
Merge remote-tracking branch 'jpa-processor/master' into feature/vers…
wog48 Oct 29, 2024
4b11745
Merge remote-tracking branch 'public/main' into feature/version-2.3.0
wog48 Oct 29, 2024
c65ee82
Enable refresh of parameter buffer by query (#355)
wog48 Nov 13, 2024
69b49b3
Merge remote-tracking branch 'jpa-processor/master' into
wog48 Nov 14, 2024
865f87c
Clean merge conflict
wog48 Nov 14, 2024
916f43d
Merge remote-tracking branch 'public/main' into feature/version-2.3.0
wog48 Nov 16, 2024
3a04f6f
Documentation for API versioning
wog48 Nov 21, 2024
73fe8f1
Merge remote-tracking branch 'public/main' into feature/version-2.3.0
wog48 Nov 21, 2024
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
274 changes: 274 additions & 0 deletions jpa-tutorial/Questions/HowToHandleApiVersions.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
= How to handle multiple API versions?

== Introduction

During the lifetime of an API it can happen that the API needs to be adopted. Some of these adoptions are incompatible.
That is, a client needs to be adopted as well to be able to handle the change. Typical incompatible changes are:

* Making a property mandatory.
* Changing the name of a property.
* Combining two properties or splitting a property.
* Removing an entity or an operation.
* ...

But even adding a non mandatory property can be incompatible in case a client can not handle unknown properties.
In all these cases the server has to provide two versions of the API till all clients have been adopted.
Starting with release 2.3.0 the JPA Processor supports multiple versions.

== Basic Idea

Instead of having a version annotation at the entities, the JPA Processor make use of multiple sets of JPA metadata.
An annotation has the risks that all entities need to be copied if one must be changed.

Metadata are (mainly) provided by the entity manager factory, so multiple entity manager factory are needed.
An option is to create multiple persistence units in the persistence.xml.
Using Spring Boot, we have also another option, which will be described below.

== Implementation


We assume that each entity or each aggregate has an own package e.g. `...model.tip` for the Trip entity and `...model.person` for the Person.
In case we like to create a new version of Trip, we need to create a new package e.g. `...model.v2.trip` and create the new version of the entity within it.

Using Spring Boot we need to make some preparation. First step is to deactivate https://www.baeldung.com/spring-open-session-in-vie[spring open session in view],
as we may get trouble having multiple beans for the entity manager factory. So we add the following to the application.yml or the corresponding to the application.properties:

[source, yaml]
----
spring:
jpa:
open-in-view: false
----

Next, we need to rearrange the creation of the entity manager factory.
First step is to create an abstract super class with the basic settings and a creation of the transaction manager:

[source, java]
----
public abstract class EclipseLinkJpaConfiguration extends JpaBaseConfiguration {

protected EclipseLinkJpaConfiguration(final DataSource dataSource, final JpaProperties properties,
final ObjectProvider<JtaTransactionManager> jtaTransactionManager) {
super(dataSource, properties, jtaTransactionManager);
}

@Override
protected AbstractJpaVendorAdapter createJpaVendorAdapter() {
return new EclipseLinkJpaVendorAdapter();
}

@Override
protected Map<String, Object> getVendorProperties() {
// https://stackoverflow.com/questions/10769051/eclipselinkjpavendoradapter-instead-of-hibernatejpavendoradapter-issue
final HashMap<String, Object> jpaProperties = new HashMap<>();
jpaProperties.put(WEAVING, "false");
// No table generation by JPA
jpaProperties.put(DDL_GENERATION, "none");
jpaProperties.put(LOGGING_LEVEL, SessionLog.FINE_LABEL);
jpaProperties.put(TRANSACTION_TYPE, "RESOURCE_LOCAL");
// do not cache entities locally, as this causes problems if multiple application instances are used
jpaProperties.put(CACHE_SHARED_DEFAULT, "false");
// You can also tweak your application performance by configuring your database connection pool.
// https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#connectionpool
jpaProperties.put(CONNECTION_POOL_MAX, 50);
return jpaProperties;
}

String[] getMapping() {
final List<String> mappingResources = this.getProperties().getMappingResources();
return (!ObjectUtils.isEmpty(mappingResources) ? StringUtils.toStringArray(mappingResources) : null);
}

PlatformTransactionManager createTransactionManager(
final ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers,
final EntityManagerFactory entityManagerFactory) {

final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
transactionManagerCustomizers
.ifAvailable((customizers) -> customizers.customize((TransactionManager) transactionManager));
return transactionManager;
}

Builder basicSettings(final EntityManagerFactoryBuilder factoryBuilder) {
final Map<String, Object> vendorProperties = getVendorProperties();
customizeVendorProperties(vendorProperties);
return factoryBuilder
.dataSource(this.getDataSource())
.properties(vendorProperties)
.mappingResources(getMapping())
.jta(false);
}
}
----

Then we need to create the version specific entity manager factories.
Please note that with each version of the entity manager factory we also have to create a transaction manager.
It is also important that one of the beans for the factory has the name `entityManagerFactory`.
First the entity manager factory for the old version:

[source, java]
----
...
import org.example.model.planitem.PlanItem;
import org.example.model.trip.Trip;
...
@Configuration
public class JpaConfigurationV1 extends EclipseLinkJpaConfiguration {

protected JpaConfigurationV1(final DataSource dataSource, final JpaProperties properties,
final ObjectProvider<JtaTransactionManager> jtaTransactionManager) {
super(dataSource, properties, jtaTransactionManager);
}

@Bean("transactionManagerFactoryV1")
PlatformTransactionManager transactionManager(
final ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers,
@Qualifier("entityManagerFactory") final EntityManagerFactory entityManagerFactory) {

return createTransactionManager(transactionManagerCustomizers, entityManagerFactory);
}

@Override
@Bean("entityManagerFactory") // A bean with this name is needed
public LocalContainerEntityManagerFactoryBean entityManagerFactory(final EntityManagerFactoryBuilder factoryBuilder,
final PersistenceManagedTypes persistenceManagedTypes) {

return basicSettings(factoryBuilder)
.packages(Trip.class, PlanItem.class, OffsetDateTimeConverter.class)
.build();
}
}
----

And then the entity manager factory for the new version.
You need to look carefully to see the difference beside the bean names.
The important call here is in `entityManagerFactory`.
We provide the `EntityManagerFactoryBuilder` classes that represent the packages that contain the JPA entities.
The difference is that Trip is now in a different package.

[source, java]
----
...
import org.example.model.planitem.PlanItem;
import org.example.model.v2.trip.Trip;
...
@Configuration
public class JpaConfigurationV2 extends EclipseLinkJpaConfiguration {

protected JpaConfigurationV2(final DataSource dataSource, final JpaProperties properties,
final ObjectProvider<JtaTransactionManager> jtaTransactionManager) {
super(dataSource, properties, jtaTransactionManager);
}

@Bean("transactionManagerFactoryV2")
PlatformTransactionManager transactionManager(
final ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers,
@Qualifier("entityManagerFactoryV2") final EntityManagerFactory entityManagerFactoryV2) {

return createTransactionManager(transactionManagerCustomizers, entityManagerFactoryV2);
}

@Override
@Bean("entityManagerFactoryV2")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(final EntityManagerFactoryBuilder factoryBuilder,
final PersistenceManagedTypes persistenceManagedTypes) {

return basicSettings(factoryBuilder)
.packages(Trip.class, PlanItem.class, OffsetDateTimeConverter.class)
.build();
}
}
----

Now the JPA Processor needs to know that it has to handle multiple versions.
The versions are defined in the session context, which we create in `ProcessorConfiguration`.
A description for a versions contains of:

* An id to identify the version later.
* The instance of the version specific entity manager factory.
* The version specific request mapping path, which is needed to make Olingo work together with Spring.
* The (type) packages containing the enumerations and operations.
* The metadata post processor

[IMPORTANT]
====
In case there are bound operations, so functions or actions, for the changed entity, also these
need to be adjusted and the corresponding packages need to be provided.

====

Here we only look at the bare minimum:

[source, java]
----
@Bean
JPAODataSessionContextAccess sessionContext(
@Qualifier("entityManagerFactoryV2") final EntityManagerFactory entityManagerFactoryV2,
@Qualifier("entityManagerFactory") final EntityManagerFactory entityManagerFactoryV1) throws ODataException {

return JPAODataServiceContext.with()
...
.setVersions(
JPAApiVersion.with()
.setId("V1")
.setEntityManagerFactory(entityManagerFactoryV1)
.setRequestMappingPath("Trippin/v1")
.build(),
JPAApiVersion.with()
.setId("V2")
.setEntityManagerFactory(entityManagerFactoryV2)
.setRequestMappingPath("Trippin/v2")
.build())
...
----

[NOTE]
====
There are also setters for all the information provided with a version.
In case a version is provided this is taken.
Otherwise, the information from the setter.
====


With this the design time part is finished and we have to adopt the runtime part.
For each request we need to decide if it is for version one or for version two.
This is done by checking if the request URI is for version one or two.
The version id we have determined is provided to the request context:

[source, java]
----
@Bean
@Scope(scopeName = SCOPE_REQUEST)
JPAODataRequestContext requestContext() {

final HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest();

return JPAODataRequestContext.with()
...
.setVersion(determineVersion(request))
.build();
}

private String determineVersion(final HttpServletRequest request) {
return request.getRequestURI().toUpperCase().startsWith("/TRIPPIN/V2/") ? "V2" : "V1";
}
----

As a last step we have to adopt the controller, so that it accepts requests for all versions.
Alternatively, we could also create a separate controller, so we would have one accepting requests
for version 1 and one accepting requests for version 2.
But to keep things simple, we just change annotation `@RequestMapping`:

[source, java]
----
@RestController
@RequestMapping("Trippin/")
@RequestScope
public class ODataController {
...
}
----

Now we can start the service and perform requests like: `/Trippin/v1/$metadata` or `/Trippin/v2/$metadata`.