Skip to content

Commit b4ad624

Browse files
committed
Make ClientBuilderService an own bundle
- refactored package structure to make client dependencies more independent - added new client maven module - added client tracker, for Jersey readieness - added requirement annotation for client - deactivate TCK module Signed-off-by: Mark Hoffmann <m.hoffmann@data-in-motion.biz>
1 parent 2cd535f commit b4ad624

File tree

30 files changed

+445
-64
lines changed

30 files changed

+445
-64
lines changed

org.eclipse.osgitech.rest.archetype/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<parent>
55
<groupId>org.eclipse.osgi-technology.rest</groupId>
66
<artifactId>parent</artifactId>
7-
<version>1.2.3-SNAPSHOT</version>
7+
<version>1.3.0-SNAPSHOT</version>
88
<relativePath>../pom.xml</relativePath>
99
</parent>
1010

org.eclipse.osgitech.rest.bnd.library/pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
33
<modelVersion>4.0.0</modelVersion>
44
<parent>
5-
<groupId>org.eclipse.osgi-technology.rest</groupId>
6-
<artifactId>parent</artifactId>
7-
<version>1.2.3-SNAPSHOT</version>
5+
<groupId>org.eclipse.osgi-technology.rest</groupId>
6+
<artifactId>parent</artifactId>
7+
<version>1.3.0-SNAPSHOT</version>
88
<relativePath>../pom.xml</relativePath>
99
</parent>
1010

org.eclipse.osgitech.rest.bnd.project.library/pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
33
<modelVersion>4.0.0</modelVersion>
44
<parent>
5-
<groupId>org.eclipse.osgi-technology.rest</groupId>
6-
<artifactId>parent</artifactId>
7-
<version>1.2.3-SNAPSHOT</version>
5+
<groupId>org.eclipse.osgi-technology.rest</groupId>
6+
<artifactId>parent</artifactId>
7+
<version>1.3.0-SNAPSHOT</version>
88
<relativePath>../pom.xml</relativePath>
99
</parent>
1010

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
2+
<modelVersion>4.0.0</modelVersion>
3+
<parent>
4+
<groupId>org.eclipse.osgi-technology.rest</groupId>
5+
<artifactId>parent</artifactId>
6+
<version>1.3.0-SNAPSHOT</version>
7+
<relativePath>../pom.xml</relativePath>
8+
</parent>
9+
<artifactId>org.eclipse.osgitech.rest.client</artifactId>
10+
<name>JakartaREST / Jersey Client Only Adapter</name>
11+
<description>Jersey based Jakarta RESTful Web Services Client Service implementation</description>
12+
13+
<dependencies>
14+
<dependency>
15+
<groupId>${project.groupId}</groupId>
16+
<artifactId>org.eclipse.osgitech.rest</artifactId>
17+
<version>${project.version}</version>
18+
<scope>compile</scope>
19+
</dependency>
20+
<dependency>
21+
<groupId>org.glassfish.jersey.core</groupId>
22+
<artifactId>jersey-client</artifactId>
23+
</dependency>
24+
<dependency>
25+
<groupId>org.glassfish.jersey.core</groupId>
26+
<artifactId>jersey-common</artifactId>
27+
</dependency>
28+
<dependency>
29+
<groupId>jakarta.ws.rs</groupId>
30+
<artifactId>jakarta.ws.rs-api</artifactId>
31+
</dependency>
32+
<dependency>
33+
<groupId>org.osgi</groupId>
34+
<artifactId>org.osgi.framework</artifactId>
35+
</dependency>
36+
<dependency>
37+
<groupId>org.osgi</groupId>
38+
<artifactId>org.osgi.namespace.implementation</artifactId>
39+
</dependency>
40+
<dependency>
41+
<groupId>org.osgi</groupId>
42+
<artifactId>org.osgi.service.condition</artifactId>
43+
</dependency>
44+
<dependency>
45+
<groupId>org.osgi</groupId>
46+
<artifactId>org.osgi.service.component</artifactId>
47+
</dependency>
48+
<dependency>
49+
<groupId>org.osgi</groupId>
50+
<artifactId>org.osgi.service.component.annotations</artifactId>
51+
</dependency>
52+
<dependency>
53+
<groupId>org.osgi</groupId>
54+
<artifactId>org.osgi.service.jakartars</artifactId>
55+
</dependency>
56+
</dependencies>
57+
58+
<build>
59+
<plugins>
60+
<plugin>
61+
<groupId>biz.aQute.bnd</groupId>
62+
<artifactId>bnd-maven-plugin</artifactId>
63+
<executions>
64+
<execution>
65+
<id>jar</id>
66+
<goals>
67+
<goal>jar</goal>
68+
</goals>
69+
<configuration>
70+
<bnd><![CDATA[
71+
Export-Package: \
72+
org.eclipse.osgitech.rest.client,\
73+
org.eclipse.osgitech.rest.client.annotations,\
74+
org.eclipse.osgitech.rest.runtime.common,\
75+
org.eclipse.osgitech.rest.provider
76+
77+
Private-Package: \
78+
org.eclipse.osgitech.rest.client.check
79+
-noextraheaders: true
80+
-noimportjava: true
81+
]]></bnd>
82+
</configuration>
83+
</execution>
84+
</executions>
85+
</plugin>
86+
</plugins>
87+
</build>
88+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* Copyright (c) 2012 - 2022 Data In Motion and others.
3+
* All rights reserved.
4+
*
5+
* This program and the accompanying materials are made available under the terms of the
6+
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
7+
* http://www.eclipse.org/legal/epl-v20.html
8+
*
9+
* Contributors:
10+
* Data In Motion - initial API and implementation
11+
* Stefan Bishof - API and implementation
12+
* Tim Ward - implementation
13+
*/
14+
package org.eclipse.osgitech.rest.client.annotations;
15+
16+
import java.lang.annotation.Documented;
17+
import java.lang.annotation.ElementType;
18+
import java.lang.annotation.Retention;
19+
import java.lang.annotation.RetentionPolicy;
20+
import java.lang.annotation.Target;
21+
22+
import org.osgi.annotation.bundle.Requirement;
23+
import org.osgi.annotation.bundle.Requirements;
24+
import org.osgi.framework.namespace.IdentityNamespace;
25+
26+
/**
27+
* Require the "client" bits of Jersey that are actually mandatory
28+
* @author Mark Hoffmann
29+
* @since 07.11.2022
30+
*/
31+
@Documented
32+
@Retention(RetentionPolicy.CLASS)
33+
@Target({
34+
ElementType.TYPE, ElementType.PACKAGE
35+
})
36+
@Requirements(value = {
37+
@Requirement(namespace = IdentityNamespace.IDENTITY_NAMESPACE, name = "org.glassfish.jersey.core.jersey-common"),
38+
@Requirement(namespace = IdentityNamespace.IDENTITY_NAMESPACE, name = "org.glassfish.jersey.core.jersey-client"),
39+
@Requirement(namespace = IdentityNamespace.IDENTITY_NAMESPACE, name = "org.glassfish.jersey.inject.jersey-hk2"),
40+
@Requirement(namespace = IdentityNamespace.IDENTITY_NAMESPACE, name = "org.glassfish.jersey.media.jersey-media-sse"),
41+
@Requirement(namespace = IdentityNamespace.IDENTITY_NAMESPACE, name = "org.glassfish.jersey.media.jersey-media-jaxb")
42+
})
43+
public @interface RequireJerseyClient {
44+
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* Copyright (c) 2012 - 2025 Data In Motion and others.
3+
* All rights reserved.
4+
*
5+
* This program and the accompanying materials are made
6+
* available under the terms of the Eclipse Public License 2.0
7+
* which is available at https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* Data In Motion - initial API and implementation
13+
*/
14+
@org.osgi.annotation.bundle.Export
15+
@org.osgi.annotation.versioning.Version("1.0.0")
16+
package org.eclipse.osgitech.rest.client.annotations;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/**
2+
* Copyright (c) 2012 - 2022 Data In Motion and others.
3+
* All rights reserved.
4+
*
5+
* This program and the accompanying materials are made available under the terms of the
6+
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
7+
* http://www.eclipse.org/legal/epl-v20.html
8+
*
9+
* Contributors:
10+
* Data In Motion - initial API and implementation
11+
*/
12+
package org.eclipse.osgitech.rest.client.check;
13+
14+
import java.util.Dictionary;
15+
import java.util.HashMap;
16+
import java.util.Hashtable;
17+
import java.util.Map;
18+
import java.util.logging.Level;
19+
import java.util.logging.Logger;
20+
21+
import org.eclipse.osgitech.rest.provider.JerseyConstants;
22+
import org.osgi.framework.Bundle;
23+
import org.osgi.framework.BundleContext;
24+
import org.osgi.framework.BundleEvent;
25+
import org.osgi.framework.BundleException;
26+
import org.osgi.framework.ServiceRegistration;
27+
import org.osgi.service.condition.Condition;
28+
import org.osgi.util.tracker.BundleTracker;
29+
import org.osgi.util.tracker.BundleTrackerCustomizer;
30+
31+
import aQute.bnd.annotation.service.ServiceCapability;
32+
33+
/**
34+
* Checker that ensures that all Jersey client bundles are started properly
35+
* to make the Jersey Client service finally start, when jersey is ready
36+
* @author Mark Hoffmann
37+
* @since 28.01.2025
38+
*/
39+
@ServiceCapability(value = Condition.class)
40+
public class JerseyClientBundleTracker implements BundleTrackerCustomizer<Boolean>{
41+
42+
private static final Logger logger = Logger.getLogger("client.check");
43+
private final Map<String, Boolean> bsns =new HashMap<>(5);
44+
private final BundleTracker<Boolean> tracker;
45+
private final BundleContext context;
46+
private ServiceRegistration<Condition> jerseyRuntimeCondition;
47+
48+
/**
49+
* Creates a new instance.
50+
* @param context the {@link BundleContext}
51+
*/
52+
public JerseyClientBundleTracker(BundleContext context) {
53+
this.context = context;
54+
bsns.put("org.glassfish.hk2.osgi-resource-locator", Boolean.FALSE);
55+
bsns.put("org.glassfish.jersey.inject.jersey-hk2", Boolean.FALSE);
56+
bsns.put("org.glassfish.jersey.core.jersey-common", Boolean.FALSE);
57+
bsns.put("org.glassfish.jersey.core.jersey-client", Boolean.FALSE);
58+
startBundles();
59+
tracker = new BundleTracker<Boolean>(context, Bundle.ACTIVE, this);
60+
}
61+
62+
/**
63+
* Opens the tracker
64+
*/
65+
public void open() {
66+
tracker.open();
67+
}
68+
69+
/**
70+
* Close the tracker
71+
*/
72+
public void close() {
73+
tracker.close();
74+
}
75+
76+
/*
77+
* (non-Javadoc)
78+
* @see org.osgi.util.tracker.BundleTrackerCustomizer#addingBundle(org.osgi.framework.Bundle, org.osgi.framework.BundleEvent)
79+
*/
80+
@Override
81+
public Boolean addingBundle(Bundle bundle, BundleEvent event) {
82+
String bsn = bundle.getSymbolicName();
83+
if (bsns.containsKey(bsn)) {
84+
bsns.put(bsn, Boolean.TRUE);
85+
updateCondition();
86+
return true;
87+
}
88+
return false;
89+
}
90+
91+
/*
92+
* (non-Javadoc)
93+
* @see org.osgi.util.tracker.BundleTrackerCustomizer#modifiedBundle(org.osgi.framework.Bundle, org.osgi.framework.BundleEvent, java.lang.Object)
94+
*/
95+
@Override
96+
public void modifiedBundle(Bundle bundle, BundleEvent event, Boolean object) {
97+
// No modification can happen
98+
}
99+
100+
/*
101+
* (non-Javadoc)
102+
* @see org.osgi.util.tracker.BundleTrackerCustomizer#removedBundle(org.osgi.framework.Bundle, org.osgi.framework.BundleEvent, java.lang.Object)
103+
*/
104+
@Override
105+
public void removedBundle(Bundle bundle, BundleEvent event, Boolean object) {
106+
String bsn = bundle.getSymbolicName();
107+
if (bsns.containsKey(bsn)) {
108+
bsns.put(bsn, Boolean.FALSE);
109+
logger.log(Level.WARNING, ()->"Removed Jersey bundle: " + bsn);
110+
updateCondition();
111+
}
112+
}
113+
114+
/**
115+
* Starts all defined bundles that are necessary to get Jersey running properly
116+
*/
117+
private void startBundles() {
118+
for (Bundle bundle : context.getBundles()) {
119+
String bsn = bundle.getSymbolicName();
120+
if (bsns.containsKey(bsn)) {
121+
try {
122+
bundle.start();
123+
} catch (BundleException e) {
124+
logger.log(Level.WARNING, e, ()->"Cannot start Jersey bundle: " + bsn);
125+
}
126+
}
127+
}
128+
}
129+
130+
/**
131+
* Updates the Jersey Runtime Condition. It will be removed, if not all needed bundles are started.
132+
* It will be registered, if all needed bundles are started
133+
*/
134+
private synchronized void updateCondition() {
135+
if (!bsns.containsValue(Boolean.FALSE)) {
136+
if (jerseyRuntimeCondition != null) {
137+
logger.info(()->"Jersey runtime condition is already registered! This should not happen! Doing nothing ...");
138+
}
139+
Dictionary<String, Object> properties = new Hashtable<String, Object>();
140+
properties.put(Condition.CONDITION_ID, JerseyConstants.JERSEY_CLIENT);
141+
properties.put(JerseyConstants.JERSEY_CLIENT_ONLY, Boolean.TRUE);
142+
jerseyRuntimeCondition = context.registerService(Condition.class, Condition.INSTANCE, properties);
143+
logger.info(()->"Registered Jersey runtime condition");
144+
} else {
145+
if (jerseyRuntimeCondition != null) {
146+
jerseyRuntimeCondition.unregister();
147+
jerseyRuntimeCondition = null;
148+
logger.info(()->"Un-registered Jersey runtime condition");
149+
}
150+
}
151+
}
152+
153+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* Copyright (c) 2012 - 2022 Data In Motion and others.
3+
* All rights reserved.
4+
*
5+
* This program and the accompanying materials are made available under the terms of the
6+
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
7+
* http://www.eclipse.org/legal/epl-v20.html
8+
*
9+
* Contributors:
10+
* Data In Motion - initial API and implementation
11+
* Stefan Bishof - API and implementation
12+
* Tim Ward - implementation
13+
*/
14+
package org.eclipse.osgitech.rest.client.check;
15+
16+
import org.osgi.framework.BundleContext;
17+
import org.osgi.service.component.annotations.Activate;
18+
import org.osgi.service.component.annotations.Component;
19+
import org.osgi.service.component.annotations.Deactivate;
20+
import org.osgi.service.condition.Condition;
21+
22+
import aQute.bnd.annotation.service.ServiceCapability;
23+
24+
/**
25+
* Component to check the Jersey client readiness and raises a condition
26+
* @author Mark Hoffmann
27+
* @since 28.01.2025
28+
*/
29+
@Component(immediate = true)
30+
@ServiceCapability(value = Condition.class)
31+
public class JerseyClientRuntimeCheck {
32+
33+
private JerseyClientBundleTracker jerseyTracker;
34+
35+
@Activate
36+
public void activate(BundleContext ctx) {
37+
jerseyTracker = new JerseyClientBundleTracker(ctx);
38+
jerseyTracker.open();
39+
40+
}
41+
42+
@Deactivate
43+
public void deactivate() {
44+
jerseyTracker.close();
45+
}
46+
47+
}

0 commit comments

Comments
 (0)