Skip to content

Commit

Permalink
Special treatment for ParamConverterProviders with multiple apps (mas…
Browse files Browse the repository at this point in the history
…ter) (helidon-io#3857)

* Special treatment for ParamConverterProviders with multiple apps (helidon-io#3846)

* Special treatment for ParamConverterProviders. They are now all registered in the shared injection manager when more than one application is present. This ensures they are all properly installed; otherwise, Jersey will only consider those known after the first of the applications is registered.

Signed-off-by: Santiago Pericasgeertsen <[email protected]>

* Updated copyright year.

Signed-off-by: Santiago Pericasgeertsen <[email protected]>

* New approach that calls getClasses/getSingletons and does require finding ParamConverterProviders via class scanning.

Signed-off-by: Santiago Pericasgeertsen <[email protected]>

* Restore ExceptionMapper registration statement.

Signed-off-by: Santiago Pericasgeertsen <[email protected]>

* Fixed support for singletons and additional testing.

Signed-off-by: Santiago Pericasgeertsen <[email protected]>

* Fixed Helidon version after cherry-pick.

Signed-off-by: Santiago Pericasgeertsen <[email protected]>

* Fixed imports.

Signed-off-by: Santiago Pericasgeertsen <[email protected]>

* Renamed javax packages in imports.

Signed-off-by: Santiago Pericasgeertsen <[email protected]>
  • Loading branch information
spericas authored Feb 2, 2022
1 parent 6aa61e3 commit eb365be
Show file tree
Hide file tree
Showing 15 changed files with 507 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import io.helidon.common.Prioritized;
import io.helidon.common.configurable.ServerThreadPoolSupplier;
Expand All @@ -59,12 +60,16 @@
import jakarta.enterprise.event.Observes;
import jakarta.enterprise.inject.spi.Bean;
import jakarta.enterprise.inject.spi.BeanManager;
import jakarta.enterprise.inject.spi.CDI;
import jakarta.enterprise.inject.spi.DeploymentException;
import jakarta.enterprise.inject.spi.Extension;
import jakarta.enterprise.inject.spi.ProcessManagedBean;
import jakarta.enterprise.inject.spi.ProcessProducerField;
import jakarta.enterprise.inject.spi.ProcessProducerMethod;
import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.ext.ParamConverterProvider;
import org.eclipse.microprofile.config.ConfigProvider;
import org.glassfish.jersey.internal.inject.Bindings;
import org.glassfish.jersey.internal.inject.InjectionManager;
import org.glassfish.jersey.internal.inject.Injections;

Expand Down Expand Up @@ -232,6 +237,25 @@ private void registerJaxRsApplications(BeanManager beanManager) {
boolean singleManager = config.get("server.single-injection-manager").asBoolean().asOptional().orElse(false);
InjectionManager shared = jaxRsApplications.size() == 1 || singleManager ? null
: Injections.createInjectionManager();

// If multiple apps, register all ParamConverterProvider's in shared manager to prevent
// only those associated with the first application to be installed by Jersey
if (shared != null) {
List<? extends Application> instances = jaxRsApplications.stream()
.flatMap(app -> app.applicationClass().stream())
.flatMap(c -> CDI.current().select(c).stream())
.collect(Collectors.toList());
instances.stream()
.flatMap(i -> i.getClasses().stream())
.filter(ParamConverterProvider.class::isAssignableFrom)
.forEach(c -> shared.register(Bindings.serviceAsContract(c).to(ParamConverterProvider.class)));
instances.stream()
.flatMap(i -> i.getSingletons().stream())
.filter(s -> s instanceof ParamConverterProvider)
.forEach(s -> shared.register(Bindings.service(s)));
}

// Add all applications
jaxRsApplications.forEach(it -> addApplication(jaxRs, it, shared));
}
STARTUP_LOGGER.finest("Registered jersey application(s)");
Expand Down
63 changes: 63 additions & 0 deletions tests/functional/param-converter-provider/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2022 Oracle and/or its affiliates.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>helidon-tests-functional-project</artifactId>
<groupId>io.helidon.tests.functional</groupId>
<version>3.0.0-SNAPSHOT</version>
</parent>

<artifactId>helidon-tests-param-converter-provider</artifactId>
<name>Helidon Functional Test: ParamConverterProviders and injection managers</name>

<dependencies>
<dependency>
<groupId>io.helidon.microprofile.bundles</groupId>
<artifactId>helidon-microprofile</artifactId>
</dependency>
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jandex</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.helidon.microprofile.tests</groupId>
<artifactId>helidon-microprofile-tests-junit5</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.helidon.tests.functional.paramconverterprovider;

import java.util.Set;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.ext.ParamConverterProvider;

@ApplicationScoped
public class Application1 extends Application {

private final ParamConverterProvider provider = new ParamConverterProvider3();

@Override
public Set<Class<?>> getClasses() {
return Set.of(Resource1.class, ParamConverterProvider1.class);
}

@Override
public Set<Object> getSingletons() {
return Set.of(provider);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.helidon.tests.functional.paramconverterprovider;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.core.Application;
import java.util.Set;

@ApplicationScoped
public class Application2 extends Application {

@Override
public Set<Class<?>> getClasses() {
return Set.of(Resource2.class, ParamConverterProvider2.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.helidon.tests.functional.paramconverterprovider;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({java.lang.annotation.ElementType.PARAMETER,
java.lang.annotation.ElementType.METHOD,
java.lang.annotation.ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ParamConverterAnnotation {

String value();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.helidon.tests.functional.paramconverterprovider;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.ext.ParamConverter;
import jakarta.ws.rs.ext.ParamConverterProvider;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

@ApplicationScoped
public class ParamConverterProvider1 implements ParamConverterProvider {

public ParamConverterProvider1() {
TestCollector.PARAM_CONVERTER_PROVIDERS.add(getClass());
}

public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
return new ParamConverter<T>() {
@Override
public T fromString(String value) {
return null;
}

@Override
public String toString(T value) {
return null;
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.helidon.tests.functional.paramconverterprovider;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.ext.ParamConverter;
import jakarta.ws.rs.ext.ParamConverterProvider;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

@ApplicationScoped
public class ParamConverterProvider2 implements ParamConverterProvider {

public ParamConverterProvider2() {
TestCollector.PARAM_CONVERTER_PROVIDERS.add(getClass());
}

@Override
public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
return new ParamConverter<T>() {
@Override
public T fromString(String value) {
return null;
}

@Override
public String toString(T value) {
return null;
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.helidon.tests.functional.paramconverterprovider;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.ext.ParamConverter;
import jakarta.ws.rs.ext.ParamConverterProvider;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

@ApplicationScoped
public class ParamConverterProvider3 implements ParamConverterProvider {

public ParamConverterProvider3() {
TestCollector.PARAM_CONVERTER_PROVIDERS.add(getClass());
}

@Override
public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
return new ParamConverter<T>() {
@Override
public T fromString(String value) {
return null;
}

@Override
public String toString(T value) {
return null;
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.helidon.tests.functional.paramconverterprovider;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.QueryParam;

@Path("hello1")
public class Resource1 {

@GET
public String get(@QueryParam("foo") @ParamConverterAnnotation("bar") String s) {
return "hello";
}
}
Loading

0 comments on commit eb365be

Please sign in to comment.