Skip to content

Commit 3bc45cd

Browse files
authored
REST Inbound connectors without multiple verbs (#284)
* Remove possibility to add multiple http methods to REST DSL in inbound connectors * Changelog and formatting * Add docs-snapshot
1 parent de9b33e commit 3bc45cd

File tree

8 files changed

+258
-41
lines changed

8 files changed

+258
-41
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"author": "Nemikor",
3+
"pullrequestId": "284",
4+
"message": "Forbid usage of multiple REST DSL verbs for different HTTP methods in a single Rest inbound connector."
5+
}
+200
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
# SIP Framework version upgrade
2+
3+
[TOC]
4+
5+
## Upgrade from 3.6.1 to x.y.z
6+
7+
Building REST inbound connectors was changed.
8+
Usage of multiple HTTP methods in REST DSL of a single connector is no longer allowed.
9+
REST Connectors which contain this should be split into their own connector implementations.
10+
This change will not affect how the adapter behaves.
11+
12+
**Note:** Unique connector ID should be assigned to each new connector,
13+
since the automatically generated one may be duplicated.
14+
15+
## Upgrade from 3.5.0 to 3.6.0
16+
17+
This version contains upgrades to major libraries used by the framework.
18+
There is a possibility that they may lead to some changes.
19+
20+
Please use the following Apache Camel guide if necessary: https://camel.apache.org/manual/camel-4x-upgrade-guide.html
21+
22+
## Upgrade from 3.4.0 to 3.5.0
23+
24+
This is a quality of life and bugfix update, it shouldn't introduce any breaking issues.
25+
26+
## Upgrade from 3.3.0 to 3.4.0
27+
28+
Version 3.4.0 allows fine-grained configuration and exception handling for connectors.
29+
If an adapter contains global configuration which was added directly with **RouteConfigurationBuilder**,
30+
it will no longer apply to connectors.
31+
It should be refactored and provided via **ConfigurationDefinition**.
32+
33+
**Note:** When it comes to process orchestration global configuration will still be applicable.
34+
35+
**Deprecation Notice**
36+
37+
The `defineTransformationOrchestrator` method from **ConnectorBase** class is marked as deprecated as of version 3.4.0.
38+
This method may be removed in future versions.
39+
It is recommended to migrate to new **Connector Processors** in all connectors.
40+
41+
## Upgrade from 3.2.0 to 3.3.0
42+
43+
This is mostly a dependencies update and bugfix version, so it's shouldn't introduce any braking changes.
44+
However, in the previous version, Integration Scenario model validation was triggered conditionally
45+
depending on the presence of Connector's response model (instead of Integration Scenario's).
46+
This has been changed, and the response transformation in the connector is now triggered unconditionally as well.
47+
48+
A runtime **validation** error will occur if an Adapter relied on that condition and **didn't conform** to Scenario's **domain model**.
49+
50+
## Upgrade from 3.1.0 to 3.2.0
51+
Version 3.2.0 introduces changes in dependencies - most notably Spring 6, Apache Camel 4 and CXF 4.
52+
There should be no breaking changes in this release. If the adapter developers relied on deprecated features from underlying frameworks then some changes are necessary but those should be fixed on case-by-case basis.
53+
54+
Upgrade guide for specific use-cases:
55+
* Adapters using **SOAP** Connectors
56+
57+
From adapter pom.xml file remove this plugin:
58+
```xml
59+
<plugin>
60+
<groupId>de.codecentric</groupId>
61+
<artifactId>cxf-spring-boot-starter-maven-plugin</artifactId>
62+
...
63+
</plugin>
64+
```
65+
and change it to:
66+
```xml
67+
<plugin>
68+
<groupId>org.apache.cxf</groupId>
69+
<artifactId>cxf-codegen-plugin</artifactId>
70+
</plugin>
71+
```
72+
Plugin is now managed in the parent pom so no further configuration is necessary. It is a standard CXF plugin and adapter developers can customize its behaviour if needed.
73+
74+
75+
* Adapters redefining **Spring Security**:
76+
If the adapter has redefined Spring Security configuration, exclusion of SIP Security was necessary:
77+
For example:
78+
```java
79+
@SIPIntegrationAdapter(exclude = SIPSecurityAutoConfiguration.class)
80+
```
81+
That should no longer be necessary, SIP has upgraded to Spring Security 6 and should work with specific behaviour redefined in the adapter.
82+
83+
84+
## Upgrade from 1.0.0 to 2.0.0
85+
86+
The following text represents the complete guide how to update SIP framework version in your adapter from version
87+
`1.0.0` to `2.0.0`.
88+
89+
In case adapter is generated with archetype of `2.0.0` framework version, following steps are not necessary. To insure
90+
your adapter uses all functionalities, the following changes have to be done manually. Please follow the guide
91+
step by step.
92+
93+
Single lines necessary for updating are marked with `update` comment.
94+
95+
First step is to update the parent field `version` in project root `pom.xml` file:
96+
97+
```xml
98+
<parent>
99+
<groupId>de.ikor.sip.foundation</groupId>
100+
<artifactId>sip-framework</artifactId>
101+
<version>2.0.0</version> <!-- update -->
102+
<relativePath/>
103+
</parent>
104+
```
105+
106+
In the same file, profile fields `id` and `maxJdkVersion` should be updated to java version 11.
107+
108+
```xml
109+
<profiles>
110+
<profile>
111+
<id>enforce-java-11</id> <!-- update -->
112+
<build>
113+
<plugins>
114+
<plugin>
115+
<groupId>org.apache.maven.plugins</groupId>
116+
<artifactId>maven-enforcer-plugin</artifactId>
117+
<version>3.0.0-M3</version>
118+
<dependencies>
119+
<dependency>
120+
<groupId>org.codehaus.mojo</groupId>
121+
<artifactId>extra-enforcer-rules</artifactId>
122+
<version>1.3</version>
123+
</dependency>
124+
</dependencies>
125+
<executions>
126+
<execution>
127+
<id>enforce-bytecode-version</id>
128+
<goals>
129+
<goal>enforce</goal>
130+
</goals>
131+
<configuration>
132+
<rules>
133+
<enforceBytecodeVersion>
134+
<maxJdkVersion>11</maxJdkVersion> <!-- update -->
135+
</enforceBytecodeVersion>
136+
</rules>
137+
<fail>true</fail>
138+
</configuration>
139+
</execution>
140+
</executions>
141+
</plugin>
142+
</plugins>
143+
</build>
144+
</profile>
145+
</profiles>
146+
```
147+
148+
Next step is to update `pom.xml` file in adapter's application module. Change the parent field `version`:
149+
150+
```xml
151+
<parent>
152+
<groupId>de.ikor.sip.foundation</groupId>
153+
<artifactId>sip-starter-parent</artifactId>
154+
<version>2.0.0</version> <!-- update -->
155+
<relativePath/>
156+
</parent>
157+
```
158+
159+
In the same file, `spring-boot-maven-plugin` must be modified. Add goal `build-info` and it's additional
160+
configuration. Simply copy the lines marked with comment `update` and add them to your code in a proper place:
161+
162+
```xml
163+
<plugin>
164+
<groupId>org.springframework.boot</groupId>
165+
<artifactId>spring-boot-maven-plugin</artifactId>
166+
<configuration>
167+
<fork>false</fork>
168+
<skip>false</skip>
169+
</configuration>
170+
<executions>
171+
<execution>
172+
<goals>
173+
<goal>repackage</goal>
174+
<goal>build-info</goal> <!-- update -->
175+
</goals>
176+
<configuration> <!-- update -->
177+
<additionalProperties> <!-- update -->
178+
<sipFrameworkVersion>2.0.0</sipFrameworkVersion> <!-- update -->
179+
</additionalProperties> <!-- update -->
180+
</configuration> <!-- update -->
181+
</execution>
182+
</executions>
183+
</plugin>
184+
```
185+
186+
Newer version requires moving your markdown files in adapter's application module under `main/resources/documents` directory.
187+
Furthermore, it is strictly required to create `documents` folder and to keep markdown files inside, so the
188+
[markdown files API](./core.md#sip-details-in-actuator-info-endpoint) can work properly.
189+
190+
If you intend to use SIP Test Kit, you should add `application.yml` in your application module `src/test/resources`
191+
directory with test profile configured:
192+
193+
```yaml
194+
spring:
195+
profiles:
196+
active: test
197+
```
198+
199+
Additionally `logback-test.xml` should be added in the same test directory. You can find the content of this file
200+
[here](../sip-archetype/src/main/resources/archetype-resources/__rootArtifactId__-application/src/test/resources/logback-test.xml).

sip-core/src/main/java/de/ikor/sip/foundation/core/declarative/AdapterBuilder.java

+17-20
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,10 @@ private <T extends OptionalIdentifiedDefinition<T>> void buildInboundConnector(
176176

177177
// Channel all inbound camel endpoint routes to the orchestration route
178178
final var endpointDefinitionType = inboundConnector.getEndpointDefinitionTypeClass();
179-
List<String> directRoutes =
180-
inboundConnector.defineInboundEndpoints(
181-
resolveConnectorDefinitionType(endpointDefinitionType),
182-
requestOrchestrationRouteId,
183-
routesRegistry);
179+
inboundConnector.defineInboundEndpoints(
180+
resolveConnectorDefinitionType(endpointDefinitionType),
181+
requestOrchestrationRouteId,
182+
routesRegistry);
184183

185184
// Build scenario handoff and response-route
186185
String routeConfigurationIds =
@@ -218,26 +217,24 @@ private <T extends OptionalIdentifiedDefinition<T>> void buildInboundConnector(
218217
handoffRouteDefinition.to(StaticEndpointBuilders.direct(responseOrchestrationRouteId));
219218

220219
// Build orchestration route(s) to/from scenario
220+
final var requestRouteDefinition =
221+
from(StaticEndpointBuilders.direct(requestOrchestrationRouteId))
222+
.routeId(requestOrchestrationRouteId)
223+
.routeConfigurationId(routeConfigurationIds);
224+
appendOnException(inboundConnector, requestRouteDefinition);
221225
final RouteDefinition responseRouteDefinition =
222226
from(StaticEndpointBuilders.direct(responseOrchestrationRouteId))
223227
.routeId(responseOrchestrationRouteId)
224228
.routeConfigurationId(routeConfigurationIds);
225229
appendOnException(inboundConnector, responseRouteDefinition);
226-
directRoutes.forEach(
227-
route -> {
228-
final var requestRouteDefinition =
229-
from(StaticEndpointBuilders.direct(route))
230-
.routeId(route)
231-
.routeConfigurationId(routeConfigurationIds);
232-
appendOnException(inboundConnector, requestRouteDefinition);
233-
var orchestrationInfo =
234-
new OrchestrationRoutes(requestRouteDefinition, Optional.of(responseRouteDefinition));
235-
236-
if (inboundConnector.getOrchestrator().canOrchestrate(orchestrationInfo)) {
237-
inboundConnector.getOrchestrator().doOrchestrate(orchestrationInfo);
238-
}
239-
requestRouteDefinition.to(StaticEndpointBuilders.direct(scenarioHandoffRouteId));
240-
});
230+
231+
var orchestrationInfo =
232+
new OrchestrationRoutes(requestRouteDefinition, Optional.of(responseRouteDefinition));
233+
234+
if (inboundConnector.getOrchestrator().canOrchestrate(orchestrationInfo)) {
235+
inboundConnector.getOrchestrator().doOrchestrate(orchestrationInfo);
236+
}
237+
requestRouteDefinition.to(StaticEndpointBuilders.direct(scenarioHandoffRouteId));
241238
}
242239

243240
private void buildOutboundConnector(

sip-core/src/main/java/de/ikor/sip/foundation/core/declarative/connector/GenericInboundConnectorBase.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import de.ikor.sip.foundation.core.declarative.annonation.InboundConnector;
88
import de.ikor.sip.foundation.core.declarative.model.MarshallerDefinition;
99
import de.ikor.sip.foundation.core.declarative.model.UnmarshallerDefinition;
10-
import java.util.List;
1110
import java.util.Optional;
1211
import org.apache.camel.builder.EndpointConsumerBuilder;
1312
import org.apache.camel.builder.endpoint.StaticEndpointBuilders;
@@ -28,7 +27,7 @@ public abstract class GenericInboundConnectorBase extends InboundConnectorBase
2827
implements InboundConnectorDefinition<RoutesDefinition> {
2928

3029
@Override
31-
public final List<String> defineInboundEndpoints(
30+
public final void defineInboundEndpoints(
3231
final RoutesDefinition definition,
3332
final String targetToBase,
3433
final RoutesRegistry routeRegistry) {
@@ -46,7 +45,6 @@ public final List<String> defineInboundEndpoints(
4645
defineRequestUnmarshalling().ifPresent(unmarshaller -> unmarshaller.accept(routeDef));
4746
routeDef.to(StaticEndpointBuilders.direct(targetToBase));
4847
defineResponseMarshalling().ifPresent(marshaller -> marshaller.accept(routeDef));
49-
return List.of(targetToBase);
5048
}
5149

5250
/**

sip-core/src/main/java/de/ikor/sip/foundation/core/declarative/connector/InboundConnectorDefinition.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import de.ikor.sip.foundation.core.declarative.RoutesRegistry;
44
import de.ikor.sip.foundation.core.declarative.scenario.IntegrationScenarioProviderDefinition;
5-
import java.util.List;
65
import org.apache.camel.builder.EndpointProducerBuilder;
76
import org.apache.camel.model.OptionalIdentifiedDefinition;
87

@@ -39,8 +38,7 @@ public non-sealed interface InboundConnectorDefinition<T extends OptionalIdentif
3938
* @param routeRegistry Route registry that must be used to register routeIds for the inbound
4039
* endpoint(s).
4140
*/
42-
List<String> defineInboundEndpoints(
43-
T definition, String targetToBase, RoutesRegistry routeRegistry);
41+
void defineInboundEndpoints(T definition, String targetToBase, RoutesRegistry routeRegistry);
4442

4543
@Override
4644
default ConnectorType getConnectorType() {

sip-core/src/main/java/de/ikor/sip/foundation/core/declarative/connector/RestInboundConnectorBase.java

+7-12
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
import de.ikor.sip.foundation.core.declarative.RoutesRegistry;
55
import de.ikor.sip.foundation.core.declarative.annonation.InboundConnector;
66
import de.ikor.sip.foundation.core.declarative.annotation.rest.ParameterMapping;
7-
import java.util.ArrayList;
8-
import java.util.List;
7+
import de.ikor.sip.foundation.core.util.exception.SIPFrameworkInitializationException;
98
import org.apache.camel.model.ToDefinition;
109
import org.apache.camel.model.rest.RestDefinition;
1110
import org.apache.camel.model.rest.RestsDefinition;
@@ -27,24 +26,20 @@ public abstract class RestInboundConnectorBase extends InboundConnectorBase
2726
implements InboundConnectorDefinition<RestsDefinition> {
2827

2928
@Override
30-
public final List<String> defineInboundEndpoints(
29+
public final void defineInboundEndpoints(
3130
final RestsDefinition definition,
3231
final String targetToBase,
3332
final RoutesRegistry routeRegistry) {
3433
var rest = definition.rest();
35-
var endpointCounter = 0;
3634
configureRest(rest);
37-
List<String> routeToPaths = new ArrayList<>();
35+
SIPFrameworkInitializationException.throwIf(
36+
rest.getVerbs().size() > 1,
37+
"Using multiple REST endpoints in one Inbound connector is not allowed");
3838
for (VerbDefinition verb : rest.getVerbs()) {
39-
verb.setId(
40-
routeRegistry.generateRouteIdForConnector(
41-
RouteRole.EXTERNAL_ENDPOINT, this, "-rest-dsl-", ++endpointCounter));
42-
String routePath = targetToBase + "-rest-dsl-" + endpointCounter;
43-
ToDefinition toDefinition = new ToDefinition("direct:" + routePath);
39+
verb.setId(routeRegistry.generateRouteIdForConnector(RouteRole.EXTERNAL_ENDPOINT, this));
40+
ToDefinition toDefinition = new ToDefinition("direct:" + targetToBase);
4441
verb.setTo(toDefinition);
45-
routeToPaths.add(routePath);
4642
}
47-
return routeToPaths;
4843
}
4944

5045
/**

sip-core/src/test/java/de/ikor/sip/foundation/core/apps/declarative/SimpleAdapter.java

+26-2
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,38 @@ public class RestDSLScenario extends IntegrationScenarioBase {
9191
}
9292

9393
@InboundConnector(
94+
connectorId = "PostRestInboundConnectorTestBase",
9495
connectorGroup = ConnectorGroupSip1.ID,
9596
integrationScenario = RestDSLScenario.ID,
9697
requestModel = String.class)
97-
public class RestInboundConnectorTestBase extends RestInboundConnectorBase {
98+
public class PostRestInboundConnectorTestBase extends RestInboundConnectorBase {
9899

99100
@Override
100101
protected void configureRest(RestDefinition definition) {
101-
definition.bindingMode("off").post("path").type(String.class).get("path");
102+
definition.bindingMode("off").post("path").type(String.class);
103+
}
104+
105+
@Override
106+
protected Orchestrator<ConnectorOrchestrationInfo> defineTransformationOrchestrator() {
107+
return ConnectorOrchestrator.forConnector(this)
108+
.setRequestRouteTransformer(this::defineRequestRoute);
109+
}
110+
111+
protected void defineRequestRoute(final RouteDefinition definition) {
112+
definition.setBody(exchange -> "PRODUCED_REST-" + exchange.getIn().getBody(String.class));
113+
}
114+
}
115+
116+
@InboundConnector(
117+
connectorId = "GetRestInboundConnectorTestBase",
118+
connectorGroup = ConnectorGroupSip1.ID,
119+
integrationScenario = RestDSLScenario.ID,
120+
requestModel = String.class)
121+
public class GetRestInboundConnectorTestBase extends RestInboundConnectorBase {
122+
123+
@Override
124+
protected void configureRest(RestDefinition definition) {
125+
definition.bindingMode("off").get("path");
102126
}
103127

104128
@Override

sip-core/src/test/java/de/ikor/sip/foundation/core/declarative/DeclarativeDefinitionEndpointTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class DeclarativeDefinitionEndpointTest {
3838

3939
private final int CONNECTORGROUPS_IN_TEST_ADAPTER = 2;
4040
private final int SCENARIOS_IN_TEST_ADAPTER = 2;
41-
private final int CONNECTORS_IN_TEST_ADAPTER = 4;
41+
private final int CONNECTORS_IN_TEST_ADAPTER = 5;
4242

4343
@Test
4444
void when_ActuatorGetAdapterDefinitionInfo_then_RetrieveFullAdapterInfo() throws IOException {

0 commit comments

Comments
 (0)