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

MicroProfile Rest Client 2.0 support #4693

Closed
wants to merge 10 commits into from
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2012, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) [2018-2019] [Payara Foundation and/or its affiliates].
* Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) [2018-2021] [Payara Foundation and/or its affiliates].
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand Down Expand Up @@ -56,7 +56,6 @@
import org.glassfish.jersey.internal.inject.InstanceBinding;
import org.glassfish.jersey.server.ApplicationHandler;
import org.glassfish.jersey.server.model.Invocable;
import org.glassfish.jersey.server.spi.ComponentProvider;
import org.glassfish.jersey.server.spi.internal.ResourceMethodInvocationHandlerProvider;

import org.glassfish.ejb.deployment.descriptor.EjbBundleDescriptorImpl;
Expand All @@ -70,6 +69,7 @@
import com.sun.ejb.containers.EjbContainerUtilImpl;
import com.sun.enterprise.config.serverbeans.Application;
import com.sun.enterprise.config.serverbeans.Applications;
import org.glassfish.jersey.server.spi.ServerComponentProvider;

/**
* EJB component provider.
Expand All @@ -79,7 +79,7 @@
*/
@Priority(300)
@SuppressWarnings("UnusedDeclaration")
public final class EjbComponentProvider implements ComponentProvider, ResourceMethodInvocationHandlerProvider {
public final class EjbComponentProvider implements ServerComponentProvider, ResourceMethodInvocationHandlerProvider {

private static final Logger LOGGER = Logger.getLogger(EjbComponentProvider.class.getName());

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package org.glassfish.jersey.client;

import org.glassfish.jersey.client.spi.ClientComponentProvider;
import java.util.Collection;
import java.util.Comparator;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import org.glassfish.jersey.internal.BootstrapBag;
import org.glassfish.jersey.internal.BootstrapConfigurator;
import org.glassfish.jersey.internal.ServiceConfigurationError;
import org.glassfish.jersey.internal.ServiceFinder;
import org.glassfish.jersey.internal.inject.InjectionManager;
import org.glassfish.jersey.internal.util.collection.LazyValue;
import org.glassfish.jersey.internal.util.collection.Value;
import org.glassfish.jersey.internal.util.collection.Values;
import org.glassfish.jersey.model.internal.RankedComparator;
import org.glassfish.jersey.model.internal.RankedProvider;
import org.glassfish.jersey.spi.ComponentProvider;

/**
* Configurator which initializes and register {@link ClientComponentProvider}
* instances into {@link BootstrapBag}.
*
*/
public class ClientComponentProviderConfigurator implements BootstrapConfigurator {

private static final Comparator<RankedProvider<ClientComponentProvider>> RANKED_COMPARATOR
= new RankedComparator<>(RankedComparator.Order.DESCENDING);

@Override
public void init(InjectionManager injectionManager, BootstrapBag bootstrapBag) {
// There are situation in which ComponentProviders are not needed therefore their entire initialization is wrapped
// into a lazy block.
LazyValue<Collection<ComponentProvider>> componentProviders
= Values.lazy((Value<Collection<ComponentProvider>>) () -> getRankedComponentProviders()
.stream()
.map(RankedProvider::getProvider)
.peek(provider -> provider.initialize(injectionManager))
.collect(Collectors.toList()));
bootstrapBag.setComponentProviders(componentProviders);
}

@Override
public void postInit(InjectionManager injectionManager, BootstrapBag bootstrapBag) {
bootstrapBag.getComponentProviders().get().forEach(ComponentProvider::done);
}

private static Collection<RankedProvider<ClientComponentProvider>> getRankedComponentProviders()
throws ServiceConfigurationError {
return StreamSupport.stream(ServiceFinder.find(ClientComponentProvider.class).spliterator(), false)
.map(RankedProvider::new)
.sorted(RANKED_COMPARATOR)
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ private ClientRuntime initRuntime() {
new RequestScope.RequestScopeConfigurator(),
new ParamConverterConfigurator(),
new ParameterUpdaterConfigurator(),
new ClientComponentProviderConfigurator(),
new RuntimeConfigConfigurator(runtimeCfgState),
new ContextResolverFactory.ContextResolversConfigurator(),
messageBodyWorkersConfigurator,
Expand All @@ -442,7 +443,13 @@ private ClientRuntime initRuntime() {
runtimeCfgState.configureMetaProviders(injectionManager, bootstrapBag.getManagedObjectsFinalizer());

// Bind providers.
ProviderBinder.bindProviders(runtimeCfgState.getComponentBag(), RuntimeType.CLIENT, null, injectionManager);
ProviderBinder.bindProviders(
bootstrapBag,
runtimeCfgState.getComponentBag(),
RuntimeType.CLIENT,
null,
injectionManager
);

ClientExecutorProvidersConfigurator executorProvidersConfigurator =
new ClientExecutorProvidersConfigurator(runtimeCfgState.getComponentBag(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ public boolean isClosed() {
*
* @throws IllegalStateException in case the client instance has been closed already.
*/
void checkNotClosed() {
protected void checkNotClosed() {
checkState(!closedFlag.get(), LocalizationMessages.CLIENT_INSTANCE_CLOSED());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand Down Expand Up @@ -47,10 +47,10 @@
*/
public class JerseyClientBuilder extends ClientBuilder {

private final ClientConfig config;
private HostnameVerifier hostnameVerifier;
private SslConfigurator sslConfigurator;
private SSLContext sslContext;
protected final ClientConfig config;
protected HostnameVerifier hostnameVerifier;
protected SslConfigurator sslConfigurator;
protected SSLContext sslContext;

private static final List<ClientBuilderListener> CLIENT_BUILDER_LISTENERS;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public URI getUri() {
}
}

private void checkNotClosed() {
protected void checkNotClosed() {
config.getClient().checkNotClosed();
}

Expand Down Expand Up @@ -149,7 +149,7 @@ public JerseyWebTarget queryParam(String name, Object... values) throws NullPoin
return new JerseyWebTarget(JerseyWebTarget.setQueryParam(getUriBuilder(), name, values), this);
}

private static UriBuilder setQueryParam(UriBuilder uriBuilder, String name, Object[] values) {
protected static UriBuilder setQueryParam(UriBuilder uriBuilder, String name, Object[] values) {
if (values == null || values.length == 0 || (values.length == 1 && values[0] == null)) {
return uriBuilder.replaceQueryParam(name, (Object[]) null);
}
Expand All @@ -158,7 +158,7 @@ private static UriBuilder setQueryParam(UriBuilder uriBuilder, String name, Obje
return uriBuilder.queryParam(name, values);
}

private static void checkForNullValues(String name, Object[] values) {
protected static void checkForNullValues(String name, Object[] values) {
Preconditions.checkNotNull(name, "name is 'null'.");

List<Integer> indexes = new LinkedList<Integer>();
Expand Down Expand Up @@ -271,7 +271,7 @@ public JerseyWebTarget resolveTemplatesFromEncoded(Map<String, Object> templateV
* @throws NullPointerException if the name-value map or any of the names or encoded values in the map
* is {@code null}.
*/
private void checkTemplateValues(final Map<String, Object> templateValues) throws NullPointerException {
protected void checkTemplateValues(final Map<String, Object> templateValues) throws NullPointerException {
Preconditions.checkNotNull(templateValues, "templateValues is 'null'.");

for (final Map.Entry entry : templateValues.entrySet()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/

package org.glassfish.jersey.client.spi;

import org.glassfish.jersey.spi.ComponentProvider;

/**
* Component provider interface to allow custom management of 3rd party
* components life-cycle and dependency injection.
* <p />
* An implementation (a component-provider) identifies itself by placing a provider-configuration
* file (if not already present), {@code org.glassfish.jersey.client.spi.ClientComponentProvider}
* in the resource directory <tt>META-INF/services</tt>, and adding the fully
* qualified service-provider-class of the implementation in the file.
*
* Jersey will not even try to inject component provider instances with Jersey artifacts.
* The SPI providers should be designed so that no dependency injection is needed at the bind time phase.

*/
public interface ClientComponentProvider extends ComponentProvider {

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand All @@ -17,15 +17,19 @@
package org.glassfish.jersey.internal;

import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

import javax.ws.rs.core.Configuration;
import javax.ws.rs.core.GenericType;

import org.glassfish.jersey.internal.spi.AutoDiscoverable;
import org.glassfish.jersey.internal.util.collection.LazyValue;
import org.glassfish.jersey.message.MessageBodyWorkers;
import org.glassfish.jersey.model.internal.ManagedObjectsFinalizer;
import org.glassfish.jersey.process.internal.RequestScope;
import org.glassfish.jersey.spi.ComponentProvider;
import org.glassfish.jersey.spi.ContextResolvers;
import org.glassfish.jersey.spi.ExceptionMappers;

Expand All @@ -45,6 +49,7 @@ public class BootstrapBag {
private ContextResolvers contextResolvers;
private ManagedObjectsFinalizer managedObjectsFinalizer;
private List<AutoDiscoverable> autoDiscoverables;
private LazyValue<Collection<ComponentProvider>> componentProviders;

/**
* Gets a list of {@link AutoDiscoverable}.
Expand Down Expand Up @@ -187,4 +192,13 @@ public void setContextResolvers(ContextResolvers contextResolvers) {
protected static void requireNonNull(Object object, Type type) {
Objects.requireNonNull(object, type + " has not been added into BootstrapBag yet");
}

public LazyValue<Collection<ComponentProvider>> getComponentProviders() {
return componentProviders;
}

public void setComponentProviders(LazyValue<Collection<ComponentProvider>> componentProviders) {
this.componentProviders = componentProviders;
}
}

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand Down Expand Up @@ -27,13 +27,17 @@
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import static java.util.stream.Collectors.toSet;

import javax.ws.rs.RuntimeType;

import javax.inject.Singleton;
import org.glassfish.jersey.internal.BootstrapBag;
import org.glassfish.jersey.internal.util.collection.LazyValue;

import org.glassfish.jersey.model.ContractProvider;
import org.glassfish.jersey.model.internal.ComponentBag;
import org.glassfish.jersey.spi.ComponentProvider;

/**
* Class used for registration of the custom providers into injection manager.
Expand Down Expand Up @@ -185,23 +189,29 @@ protected void configure() {
* Bind all providers contained in {@code providerBag} (classes and instances) using injection manager. Configuration is
* also committed.
*
* @param bootstrapBag bootstrap bag with services used in following processing.
* @param componentBag bag of provider classes and instances.
* @param injectionManager injection manager the binder will use to bind the providers into.
*/
public static void bindProviders(final ComponentBag componentBag, final InjectionManager injectionManager) {
bindProviders(componentBag, null, Collections.emptySet(), injectionManager);
public static void bindProviders(
final BootstrapBag bootstrapBag,
final ComponentBag componentBag,
final InjectionManager injectionManager) {
bindProviders(bootstrapBag, componentBag, null, Collections.emptySet(), injectionManager);
}

/**
* Bind all providers contained in {@code providerBag} (classes and instances) using injection manager. Configuration is
* also committed.
*
* @param bootstrapBag bootstrap bag with services used in following processing.
* @param componentBag bag of provider classes and instances.
* @param constrainedTo current runtime (client or server).
* @param registeredClasses classes which are manually registered by the user (not found by the classpath scanning).
* @param injectionManager injection manager the binder will use to bind the providers into.
*/
public static void bindProviders(ComponentBag componentBag,
public static void bindProviders(BootstrapBag bootstrapBag,
ComponentBag componentBag,
RuntimeType constrainedTo,
Set<Class<?>> registeredClasses,
InjectionManager injectionManager) {
Expand Down Expand Up @@ -233,8 +243,20 @@ public static void bindProviders(ComponentBag componentBag,
.collect(Collectors.toSet());
}
for (final Class<?> providerClass : classes) {
final ContractProvider model = componentBag.getModel(providerClass);
binderToRegister.addAll(createProviderBinders(providerClass, model));
boolean registered = false;
LazyValue<Collection<ComponentProvider>> componentProvider = bootstrapBag.getComponentProviders();
if (componentProvider != null) {
for (ComponentProvider provider : componentProvider.get()) {
if (provider.bind(providerClass, Arrays.stream(providerClass.getInterfaces()).collect(toSet()))) {
registered = true;
}
}
}

if (!registered) {
final ContractProvider model = componentBag.getModel(providerClass);
binderToRegister.addAll(createProviderBinders(providerClass, model));
}
}

// Bind provider instances except for pure meta-providers and providers with empty contract models (e.g. resources)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand All @@ -14,7 +14,7 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/

package org.glassfish.jersey.server.spi;
package org.glassfish.jersey.spi;

import java.util.Set;

Expand All @@ -23,15 +23,7 @@
/**
* Component provider interface to allow custom management of 3rd party
* components life-cycle and dependency injection.
* <p />
* An implementation (a component-provider) identifies itself by placing a provider-configuration
* file (if not already present), {@code org.glassfish.jersey.server.spi.ComponentProvider}
* in the resource directory <tt>META-INF/services</tt>, and adding the fully
* qualified service-provider-class of the implementation in the file.
*
* Jersey will not even try to inject component provider instances with Jersey artifacts.
* The SPI providers should be designed so that no dependency injection is needed at the bind time phase.

* @author Jakub Podlesak
*/
public interface ComponentProvider {
Expand Down
Loading