Skip to content

Commit

Permalink
Beans not injected into a service impl with @CXFEndpoint("/my-path") fix
Browse files Browse the repository at this point in the history
  • Loading branch information
ppalaga committed Jun 3, 2024
1 parent 5217d7a commit 02f027c
Show file tree
Hide file tree
Showing 10 changed files with 182 additions and 78 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.quarkiverse.cxf.deployment;

import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Stream;

Expand All @@ -11,15 +12,17 @@
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationTarget;
import org.jboss.jandex.AnnotationValue;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.IndexView;

public class CxfDeploymentUtils {

private CxfDeploymentUtils() {
}

public static Stream<AnnotationInstance> cxfEndpointAnnotations(IndexView index) {
public static Stream<AnnotationInstance> methodsWithCxfEndpointAnnotations(IndexView index) {
return Stream.of(CxfDotNames.CXF_ENDPOINT_ANNOTATION)
.map(index::getAnnotations)
.flatMap(Collection::stream)
Expand All @@ -33,6 +36,35 @@ public static Stream<AnnotationInstance> webServiceAnnotations(IndexView index)
.filter(annotation -> annotation.target().kind() == AnnotationTarget.Kind.CLASS);
}

public static String findSei(IndexView index, ClassInfo wsClassInfo) {

{
final AnnotationInstance webServiceAnnotation = wsClassInfo.annotation(CxfDotNames.WEBSERVICE_ANNOTATION);
if (webServiceAnnotation != null) {
if (wsClassInfo.isInterface()) {
return wsClassInfo.name().toString();
}
final AnnotationValue val = webServiceAnnotation.value("endpointInterface");
if (val != null) {
final String result = val.asString();
if (!result.isEmpty()) {
return result;
}
}
}
}

final List<DotName> interfaces = wsClassInfo.interfaceNames();
for (DotName interfaceName : interfaces) {
final ClassInfo interfaceInfo = index.getClassByName(interfaceName);
final AnnotationInstance webServiceAnnotation = interfaceInfo.annotation(CxfDotNames.WEBSERVICE_ANNOTATION);
if (webServiceAnnotation != null) {
return interfaceInfo.name().toString();
}
}
return wsClassInfo.name().toString();
}

/**
* Creates a server at runtime thus triggering the generation of all required classes. This includes
* CXF extensions, endpoint wrappers, etc.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,33 @@
*/
public final class CxfEndpointImplementationBuildItem extends AbstractEndpointBuildItem {

private final String sei;
private final String implementor;
private final boolean provider;
private final String relativePath;
private final BeanLookupStrategy beanLookupStrategy;

public CxfEndpointImplementationBuildItem(String implementor, String soapBinding, String wsNamespace,
String wsName, boolean provider, String relativePath, BeanLookupStrategy beanLookupStrategy) {
public CxfEndpointImplementationBuildItem(
String sei,
String implementor,
String soapBinding,
String wsNamespace,
String wsName,
boolean provider,
String relativePath,
BeanLookupStrategy beanLookupStrategy) {
super(soapBinding, wsNamespace, wsName);
this.sei = sei;
this.implementor = Objects.requireNonNull(implementor, "implementor cannot be null");
this.provider = provider;
this.relativePath = relativePath;
this.beanLookupStrategy = beanLookupStrategy;
}

public String getSei() {
return sei;
}

public String getImplementor() {
return implementor;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,15 @@ void collectEndpoints(

final AnnotationInstance cxfEndpointAnnotation = wsClassInfo
.declaredAnnotation(CxfDotNames.CXF_ENDPOINT_ANNOTATION);
final String relPath = cxfEndpointAnnotation != null ? cxfEndpointAnnotation.value().asString() : null;
final String relPath;
final BeanLookupStrategy beanLookupStrategy;
if (cxfEndpointAnnotation != null) {
relPath = cxfEndpointAnnotation.value().asString();
beanLookupStrategy = BeanLookupStrategy.TYPE_WITH_CXFENDPOINT_ANNOTATION;
} else {
relPath = null;
beanLookupStrategy = BeanLookupStrategy.TYPE;
}

submitImpl(
endpointImplementations,
Expand All @@ -90,10 +98,11 @@ void collectEndpoints(
reflectives,
annotation,
wsClassInfo,
CxfDeploymentUtils.findSei(index, wsClassInfo),
impl,
hasWebServiceProviderAnnotation,
relPath,
BeanLookupStrategy.TYPE);
beanLookupStrategy);

} else if (Modifier.isInterface(wsClassInfo.flags())) {
String cl = wsClassInfo.name().toString();
Expand All @@ -107,12 +116,13 @@ void collectEndpoints(
}

});
CxfDeploymentUtils.cxfEndpointAnnotations(index)
CxfDeploymentUtils.methodsWithCxfEndpointAnnotations(index)
.forEach(annotation -> {
final MethodInfo methodInfo = annotation.target().asMethod();

final String impl = methodInfo.returnType().name().toString();
final ClassInfo wsClassInfo = index.getClassByName(methodInfo.returnType().name());
final DotName returnType = methodInfo.returnType().name();
final String impl = returnType.toString();
final ClassInfo wsClassInfo = index.getClassByName(returnType);
AnnotationInstance wsAnnot = wsClassInfo.declaredAnnotation(CxfDotNames.WEBSERVICE_ANNOTATION);
final boolean hasWebServiceProviderAnnotation = wsAnnot != null;
if (wsAnnot == null) {
Expand All @@ -131,10 +141,11 @@ void collectEndpoints(
reflectives,
wsAnnot,
wsClassInfo,
CxfDeploymentUtils.findSei(index, wsClassInfo),
impl,
hasWebServiceProviderAnnotation,
annotation.value().asString(),
BeanLookupStrategy.TYPE_WITH_CXFENDPOINT_ANNOTATION);
BeanLookupStrategy.METHOD_WITH_CXFENDPOINT_ANNOTATION);
});

reflectiveClass
Expand All @@ -146,6 +157,7 @@ private void submitImpl(
BuildProducer<ServiceSeiBuildItem> serviceSeis,
BuildProducer<AdditionalBeanBuildItem> additionalBeans, Set<String> reflectives, AnnotationInstance annotation,
ClassInfo wsClassInfo,
String sei,
String impl,
boolean hasWebServiceProviderAnnotation,
String relativePathFromCxfEndpointAnnotation,
Expand All @@ -166,7 +178,7 @@ private void submitImpl(

final String wsName = Optional.ofNullable(annotation.value("serviceName"))
.map(AnnotationValue::asString)
.orElse(impl.contains(".") ? impl.substring(impl.lastIndexOf('.') + 1) : impl);
.orElse(sei.contains(".") ? sei.substring(sei.lastIndexOf('.') + 1) : sei);

String soapBinding = Optional
.ofNullable(wsClassInfo.declaredAnnotation(CxfDotNames.BINDING_TYPE_ANNOTATION))
Expand All @@ -175,6 +187,7 @@ private void submitImpl(

endpointImplementations.produce(
new CxfEndpointImplementationBuildItem(
sei,
impl,
soapBinding,
wsNamespace,
Expand Down Expand Up @@ -204,21 +217,27 @@ CXFServletInfosBuildItem startRoute(CXFRecorder recorder,
.collect(Collectors.toList());
if (!cxfEndpoints.isEmpty()) {
RuntimeValue<Map<String, List<ServletConfig>>> implementorToCfgMap = recorder.implementorToCfgMap(cxfConfig);

final ClassLoader cl = Thread.currentThread().getContextClassLoader();
for (CxfEndpointImplementationBuildItem cxfWebService : cxfEndpoints) {
recorder.addCxfServletInfo(
infos,
implementorToCfgMap,
fixedConfig.path(),
cxfWebService.getImplementor(),
cxfConfig,
cxfWebService.getWsName(),
cxfWebService.getWsNamespace(),
cxfWebService.getSoapBinding(),
cxfWebService.getImplementor(),
cxfWebService.isProvider(),
cxfWebService.getRelativePath(),
cxfWebService.getBeanLookupStrategy());
requestors.add(cxfWebService.getImplementor());
try {
recorder.addCxfServletInfo(
infos,
implementorToCfgMap,
fixedConfig.path(),
cl.loadClass(cxfWebService.getSei()),
cxfConfig,
cxfWebService.getWsName(),
cxfWebService.getWsNamespace(),
cxfWebService.getSoapBinding(),
cl.loadClass(cxfWebService.getImplementor()),
cxfWebService.isProvider(),
cxfWebService.getRelativePath(),
cxfWebService.getBeanLookupStrategy());
requestors.add(cxfWebService.getImplementor());
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
if (!requestors.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,53 +48,60 @@ public ServletConfig(CxfEndpointConfig cxfEndPointConfig, String relativePath) {
public enum BeanLookupStrategy {
TYPE {
@Override
public Supplier<Object> createLookUp(String type, String path) {
return () -> CXFRuntimeUtils.getInstance(type, false);
public Supplier<Object> createLookUp(Class<?> sei, Class<?> wsImplementor, String path) {
return () -> CXFRuntimeUtils.getInstance(wsImplementor);
}
},
METHOD_WITH_CXFENDPOINT_ANNOTATION {
@Override
public Supplier<Object> createLookUp(Class<?> sei, Class<?> wsImplementor, String path) {
return createLookupInternal(sei, path);
}

},
TYPE_WITH_CXFENDPOINT_ANNOTATION {
@Override
public Supplier<Object> createLookUp(String type, String path) {
return () -> {
try {
Class<?> wsImplementorClass = Class.forName(type, false,
Thread.currentThread().getContextClassLoader());
Object result = Arc.container()
.instance(wsImplementorClass,
new CXFEndpoint.CXFEndpointLiteral(path))
.get();
if (result == null) {
throw new IllegalStateException("Could get bean of type " + type + " qualified by @"
+ CXFEndpoint.class.getName() + "(\"" + path + "\")");
}
return result;
} catch (ClassNotFoundException e) {
throw new RuntimeException("Could not load class " + type, e);
}
};
public Supplier<Object> createLookUp(Class<?> sei, Class<?> wsImplementor, String path) {
return createLookupInternal(wsImplementor, path);
}

};

public abstract Supplier<Object> createLookUp(String type, String path);
private static Supplier<Object> createLookupInternal(Class<?> type, String path) {
return () -> {
Object result = Arc.container()
.instance(type,
new CXFEndpoint.CXFEndpointLiteral(path))
.get();
if (result == null) {
throw new IllegalStateException("Could get bean of type " + type + " qualified by @"
+ CXFEndpoint.class.getName() + "(\"" + path + "\")");
}
return result;
};
}

public abstract Supplier<Object> createLookUp(Class<?> sei, Class<?> wsImplementor, String path);
}

public void addCxfServletInfo(
RuntimeValue<CXFServletInfos> runtimeInfos,
RuntimeValue<Map<String, List<ServletConfig>>> implementorToCfg,
String path,
String sei,
Class<?> sei,
CxfConfig cxfConfig,
String serviceName,
String serviceTargetNamepsace,
String soapBinding,
String wsImplementor,
Class<?> wsImplementor,
Boolean isProvider,
String relativePathFromCxfEndpointAnnotation,
BeanLookupStrategy beanLookupStrategy) {

CXFServletInfos infos = runtimeInfos.getValue();

switch (beanLookupStrategy) {
case METHOD_WITH_CXFENDPOINT_ANNOTATION:
case TYPE_WITH_CXFENDPOINT_ANNOTATION: {
final CxfEndpointConfig cxfEndPointConfig = cxfConfig.endpoints().get(relativePathFromCxfEndpointAnnotation);
final CXFServletInfo info = createServletInfo(
Expand All @@ -107,7 +114,7 @@ public void addCxfServletInfo(
cxfEndPointConfig,
relativePathFromCxfEndpointAnnotation,
isProvider,
beanLookupStrategy.createLookUp(sei, relativePathFromCxfEndpointAnnotation));
beanLookupStrategy.createLookUp(sei, wsImplementor, relativePathFromCxfEndpointAnnotation));
infos.add(info);
return;
}
Expand All @@ -125,11 +132,11 @@ public void addCxfServletInfo(
cxfEndPointConfig,
relativePathFromCxfEndpointAnnotation,
isProvider,
beanLookupStrategy.createLookUp(wsImplementor, relativePathFromCxfEndpointAnnotation));
beanLookupStrategy.createLookUp(sei, wsImplementor, relativePathFromCxfEndpointAnnotation));
infos.add(info);
return;
}
List<ServletConfig> cfgs = implementorToCfg.getValue().get(wsImplementor);
List<ServletConfig> cfgs = implementorToCfg.getValue().get(wsImplementor.getName());
if (cfgs != null) {
for (ServletConfig cfg : cfgs) {
CxfEndpointConfig cxfEndPointConfig = cfg.config;
Expand All @@ -144,12 +151,12 @@ public void addCxfServletInfo(
cxfEndPointConfig,
relativePath,
isProvider,
beanLookupStrategy.createLookUp(wsImplementor, relativePathFromCxfEndpointAnnotation));
beanLookupStrategy.createLookUp(sei, wsImplementor, relativePathFromCxfEndpointAnnotation));
infos.add(info);
}
} else {
if (serviceName == null || serviceName.isEmpty()) {
serviceName = sei.toLowerCase();
serviceName = sei.getName().toLowerCase();
if (serviceName.contains(".")) {
serviceName = serviceName.substring(serviceName.lastIndexOf('.') + 1);
}
Expand All @@ -165,7 +172,7 @@ public void addCxfServletInfo(
null,
relativePath,
isProvider,
beanLookupStrategy.createLookUp(wsImplementor, relativePathFromCxfEndpointAnnotation));
beanLookupStrategy.createLookUp(sei, wsImplementor, relativePathFromCxfEndpointAnnotation));
infos.add(info);
}
return;
Expand Down Expand Up @@ -198,19 +205,19 @@ public RuntimeValue<Map<String, List<ServletConfig>>> implementorToCfgMap(CxfCon

private static CXFServletInfo createServletInfo(
String path,
String sei,
Class<?> sei,
String serviceName,
String serviceTargetNamespace,
String soapBinding,
String wsImplementor,
Class<?> implementor,
CxfEndpointConfig cxfEndPointConfig,
String relativePath,
Boolean isProvider,
Supplier<Object> beanLookup) {
CXFServletInfo cfg = new CXFServletInfo(
path,
relativePath,
wsImplementor,
implementor,
sei,
cxfEndPointConfig != null ? cxfEndPointConfig.wsdlPath().orElse(null) : null,
serviceName,
Expand Down
Loading

0 comments on commit 02f027c

Please sign in to comment.