diff --git a/applications/mp/pom.xml b/applications/mp/pom.xml
index 01db13152e1..38fe118e36a 100644
--- a/applications/mp/pom.xml
+++ b/applications/mp/pom.xml
@@ -32,7 +32,7 @@
Parent pom for Helidon MP applications
- 1.0.6
+ 3.1.20.14.02.7.5.16.1.7.Final
@@ -43,7 +43,7 @@
- org.jboss.jandex
+ io.smallryejandex-maven-plugin${version.plugin.jandex}
diff --git a/applications/parent/pom.xml b/applications/parent/pom.xml
index 2590acbc805..d5c493315a8 100644
--- a/applications/parent/pom.xml
+++ b/applications/parent/pom.xml
@@ -39,7 +39,7 @@
${maven.compiler.source}${maven.compiler.source}3.8.1
- 3.1.2
+ 3.6.01.6.03.0.0-M53.0.3
@@ -108,7 +108,6 @@
truetrueruntime
- test
diff --git a/archetypes/helidon/src/main/archetype/mp/common/common-mp.xml b/archetypes/helidon/src/main/archetype/mp/common/common-mp.xml
index 84e42a8dd19..b9be77a795f 100644
--- a/archetypes/helidon/src/main/archetype/mp/common/common-mp.xml
+++ b/archetypes/helidon/src/main/archetype/mp/common/common-mp.xml
@@ -1,7 +1,7 @@
-
- io.helidon.reactive.webclient
- helidon-reactive-webclient-jaxrs
- ${helidon.version}
- io.helidon.reactive.webclienthelidon-reactive-webclient
@@ -1492,6 +1487,18 @@
${helidon.version}
+
+
+ io.helidon.integrations.oci.sdk
+ helidon-integrations-oci-sdk-processor
+ ${helidon.version}
+
+
+ io.helidon.integrations.oci.sdk
+ helidon-integrations-oci-sdk-runtime
+ ${helidon.version}
+
+
diff --git a/builder/builder-config-processor/src/main/java/io/helidon/builder/config/processor/ConfigBeanBuilderCreator.java b/builder/builder-config-processor/src/main/java/io/helidon/builder/config/processor/ConfigBeanBuilderCreator.java
index 85b2ffe1f94..38e2976d9db 100644
--- a/builder/builder-config-processor/src/main/java/io/helidon/builder/config/processor/ConfigBeanBuilderCreator.java
+++ b/builder/builder-config-processor/src/main/java/io/helidon/builder/config/processor/ConfigBeanBuilderCreator.java
@@ -50,7 +50,7 @@
import io.helidon.common.types.TypeInfo;
import io.helidon.common.types.TypeName;
import io.helidon.common.types.TypeNameDefault;
-import io.helidon.common.types.TypedElementName;
+import io.helidon.common.types.TypedElementInfo;
import io.helidon.config.metadata.ConfiguredOption;
import static io.helidon.builder.config.spi.ConfigBeanInfo.LevelType;
@@ -124,7 +124,7 @@ protected void preValidate(TypeName implTypeName,
* Generic/simple map types are not supported on config beans, only <String, <Known ConfigBean types>>.
*/
private void assertNoGenericMaps(TypeInfo typeInfo) {
- List list = typeInfo.elementInfo().stream()
+ List list = typeInfo.interestingElementInfo().stream()
.filter(it -> it.typeName().isMap())
.filter(it -> {
TypeName typeName = it.typeName();
@@ -292,7 +292,7 @@ protected void appendExtraBuilderMethods(StringBuilder builder,
int i = 0;
for (String attrName : ctx.allAttributeNames()) {
- TypedElementName method = ctx.allTypeInfos().get(i);
+ TypedElementInfo method = ctx.allTypeInfos().get(i);
String configKey = toConfigKey(attrName, method, ctx.builderTriggerAnnotation());
// resolver.of(config, "port", int.class).ifPresent(this::port);
@@ -449,7 +449,7 @@ private void javaDocAcceptResolveConfigCtx(StringBuilder builder,
}
private String toConfigKey(String attrName,
- TypedElementName method,
+ TypedElementInfo method,
AnnotationAndValue ignoredBuilderAnnotation) {
String configKey = null;
Optional extends AnnotationAndValue> configuredOptions = AnnotationAndValueDefault
@@ -473,7 +473,7 @@ private static void assertNoAnnotation(String annoTypeName,
+ " on " + typeInfo.typeName());
}
- for (TypedElementName elem : typeInfo.elementInfo()) {
+ for (TypedElementInfo elem : typeInfo.interestingElementInfo()) {
anno = AnnotationAndValueDefault.findFirst(annoTypeName, elem.annotations());
if (anno.isEmpty()) {
anno = AnnotationAndValueDefault.findFirst(annoTypeName, elem.elementTypeAnnotations());
diff --git a/builder/builder-config-processor/src/test/java/io/helidon/builder/config/processor/ConfigBeanBuilderCreatorTest.java b/builder/builder-config-processor/src/test/java/io/helidon/builder/config/processor/ConfigBeanBuilderCreatorTest.java
index c2bef78c0d6..19b231ece3f 100644
--- a/builder/builder-config-processor/src/test/java/io/helidon/builder/config/processor/ConfigBeanBuilderCreatorTest.java
+++ b/builder/builder-config-processor/src/test/java/io/helidon/builder/config/processor/ConfigBeanBuilderCreatorTest.java
@@ -29,8 +29,8 @@
import io.helidon.common.types.TypeInfoDefault;
import io.helidon.common.types.TypeName;
import io.helidon.common.types.TypeNameDefault;
-import io.helidon.common.types.TypedElementName;
-import io.helidon.common.types.TypedElementNameDefault;
+import io.helidon.common.types.TypedElementInfo;
+import io.helidon.common.types.TypedElementInfoDefault;
import org.junit.jupiter.api.Test;
@@ -111,11 +111,11 @@ void preValidateConfigBeansMustBeRootToHaveDefaults() {
@Test
void preValidateConfigBeansMustNotHaveDuplicateSingularNames() {
- TypedElementName method1 = TypedElementNameDefault.builder()
+ TypedElementInfo method1 = TypedElementInfoDefault.builder()
.elementName("socket")
.typeName(String.class)
.build();
- TypedElementName method2 = TypedElementNameDefault.builder()
+ TypedElementInfo method2 = TypedElementInfoDefault.builder()
.elementName("socketSet")
.typeName(String.class)
.addAnnotation(AnnotationAndValueDefault.create(Singular.class, "socket"))
@@ -124,7 +124,7 @@ void preValidateConfigBeansMustNotHaveDuplicateSingularNames() {
TypeInfo typeInfo = TypeInfoDefault.builder()
.typeKind(TypeInfo.KIND_INTERFACE)
.typeName(TypeNameDefault.create(getClass()))
- .elementInfo(Set.of(method1, method2))
+ .interestingElementInfo(Set.of(method1, method2))
.build();
AnnotationAndValueDefault configBeanAnno = AnnotationAndValueDefault.builder()
.typeName(TypeNameDefault.create(ConfigBean.class))
@@ -141,7 +141,7 @@ void preValidateConfigBeansMustNotHaveDuplicateSingularNames() {
@Test
void preValidateConfigBeansMustHaveMapTypesWithNestedConfigBeans() {
- TypedElementName method1 = TypedElementNameDefault.builder()
+ TypedElementInfo method1 = TypedElementInfoDefault.builder()
.elementName("socket")
.typeName(TypeNameDefault.builder()
.type(Map.class)
@@ -154,7 +154,7 @@ void preValidateConfigBeansMustHaveMapTypesWithNestedConfigBeans() {
TypeInfo typeInfo = TypeInfoDefault.builder()
.typeKind(TypeInfo.KIND_INTERFACE)
.typeName(TypeNameDefault.create(getClass()))
- .elementInfo(Set.of(method1))
+ .interestingElementInfo(Set.of(method1))
.build();
AnnotationAndValueDefault configBeanAnno = AnnotationAndValueDefault.builder()
.typeName(TypeNameDefault.create(ConfigBean.class))
@@ -172,7 +172,7 @@ void preValidateConfigBeansMustHaveMapTypesWithNestedConfigBeans() {
creator.preValidate(implTypeName, typeInfo, configBeanAnno);
// now we will validate the exceptions when ConfigBeans are attempted to be embedded
- TypedElementName method2 = TypedElementNameDefault.builder()
+ TypedElementInfo method2 = TypedElementInfoDefault.builder()
.elementName("unsupported1")
.typeName(TypeNameDefault.builder()
.type(Map.class)
@@ -182,7 +182,7 @@ void preValidateConfigBeansMustHaveMapTypesWithNestedConfigBeans() {
TypeNameDefault.create(getClass())))
.build())
.build();
- TypedElementName method3 = TypedElementNameDefault.builder()
+ TypedElementInfo method3 = TypedElementInfoDefault.builder()
.elementName("unsupported2")
.typeName(TypeNameDefault.builder()
.type(Map.class)
@@ -195,7 +195,7 @@ void preValidateConfigBeansMustHaveMapTypesWithNestedConfigBeans() {
TypeInfo typeInfo2 = TypeInfoDefault.builder()
.typeKind(TypeInfo.KIND_INTERFACE)
.typeName(TypeNameDefault.create(getClass()))
- .elementInfo(List.of(method2, method3))
+ .interestingElementInfo(List.of(method2, method3))
.referencedTypeNamesToAnnotations(Map.of(TypeNameDefault.create(getClass()),
List.of(AnnotationAndValueDefault.create(Builder.class))))
.build();
diff --git a/builder/processor-spi/src/main/java/io/helidon/builder/processor/spi/TypeInfoCreatorProvider.java b/builder/processor-spi/src/main/java/io/helidon/builder/processor/spi/TypeInfoCreatorProvider.java
index b18db69c59c..1b7bb01b295 100644
--- a/builder/processor-spi/src/main/java/io/helidon/builder/processor/spi/TypeInfoCreatorProvider.java
+++ b/builder/processor-spi/src/main/java/io/helidon/builder/processor/spi/TypeInfoCreatorProvider.java
@@ -25,7 +25,7 @@
import io.helidon.common.types.TypeInfo;
import io.helidon.common.types.TypeName;
-import io.helidon.common.types.TypedElementName;
+import io.helidon.common.types.TypedElementInfo;
/**
* Java {@link java.util.ServiceLoader} provider interface used to discover type info creators.
@@ -58,13 +58,13 @@ Optional createBuilderTypeInfo(TypeName annoTypeName,
* @param mirror the type mirror for the element being processed
* @param processingEnv the processing environment
* @param elementOfInterest the predicate filter to determine whether the element is of interest, and therefore should be
- * included in {@link TypeInfo#elementInfo()}. Otherwise, if the predicate indicates it is not of
+ * included in {@link TypeInfo#interestingElementInfo()}. Otherwise, if the predicate indicates it is not of
* interest then the method will be placed under {@link TypeInfo#otherElementInfo()} instead
* @return the type info associated with the arguments being processed, or empty if not able to process the type
*/
Optional createTypeInfo(TypeElement element,
TypeMirror mirror,
ProcessingEnvironment processingEnv,
- Predicate elementOfInterest);
+ Predicate elementOfInterest);
}
diff --git a/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/BeanUtils.java b/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/BeanUtils.java
index ba6f566493b..335f2eb78f9 100644
--- a/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/BeanUtils.java
+++ b/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/BeanUtils.java
@@ -138,7 +138,7 @@ public static boolean validateAndParseMethodName(String methodName,
* @return true if it appears to be a reserved word
*/
public static boolean isReservedWord(String word) {
- return RESERVED.get().contains(word.toUpperCase());
+ return RESERVED.get().stream().anyMatch(word::equalsIgnoreCase);
}
/**
diff --git a/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/BodyContext.java b/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/BodyContext.java
index ef254c27b01..a6885130a5c 100644
--- a/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/BodyContext.java
+++ b/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/BodyContext.java
@@ -30,7 +30,7 @@
import io.helidon.common.types.TypeInfo;
import io.helidon.common.types.TypeName;
import io.helidon.common.types.TypeNameDefault;
-import io.helidon.common.types.TypedElementName;
+import io.helidon.common.types.TypedElementInfo;
import static io.helidon.builder.processor.tools.BeanUtils.isBooleanType;
import static io.helidon.builder.processor.tools.BeanUtils.isReservedWord;
@@ -54,8 +54,8 @@ public class BodyContext {
private final TypeName implTypeName;
private final TypeInfo typeInfo;
private final AnnotationAndValue builderTriggerAnnotation;
- private final Map map = new LinkedHashMap<>();
- private final List allTypeInfos = new ArrayList<>();
+ private final Map map = new LinkedHashMap<>();
+ private final List allTypeInfos = new ArrayList<>();
private final List allAttributeNames = new ArrayList<>();
private final boolean hasStreamSupportOnImpl;
private final boolean hasStreamSupportOnBuilder;
@@ -126,10 +126,11 @@ public class BodyContext {
searchForBuilderAnnotation("interceptorCreateMethod", builderTriggerAnnotation, typeInfo);
this.interceptorCreateMethod = (interceptorCreateMethod == null || interceptorCreateMethod.isEmpty())
? null : interceptorCreateMethod;
- this.publicOrPackagePrivateDecl = (typeInfo.typeKind().equals(TypeInfo.KIND_INTERFACE)
- || typeInfo.modifierNames().isEmpty()
- || typeInfo.modifierNames().contains(TypeInfo.MODIFIER_PUBLIC))
- ? "public " : "";
+ this.publicOrPackagePrivateDecl = (
+ typeInfo.typeKind().equals(TypeInfo.KIND_INTERFACE)
+ || typeInfo.modifierNames().isEmpty()
+ || typeInfo.modifierNames().stream().anyMatch(TypeInfo.MODIFIER_PUBLIC::equalsIgnoreCase))
+ ? "public " : "";
}
@Override
@@ -179,7 +180,7 @@ public AnnotationAndValue builderTriggerAnnotation() {
*
* @return the map of elements by name
*/
- protected Map map() {
+ protected Map map() {
return map;
}
@@ -188,7 +189,7 @@ protected Map map() {
*
* @return the list of type elements
*/
- public List allTypeInfos() {
+ public List allTypeInfos() {
return allTypeInfos;
}
@@ -427,7 +428,7 @@ public Optional interceptorCreateMethod() {
*/
public boolean hasOtherMethod(String name,
TypeInfo typeInfo) {
- for (TypedElementName elem : typeInfo.otherElementInfo()) {
+ for (TypedElementInfo elem : typeInfo.otherElementInfo()) {
if (elem.elementName().equals(name)) {
return true;
}
@@ -447,7 +448,7 @@ public boolean hasOtherMethod(String name,
* @param isBeanStyleRequired is bean style required
* @return the bean attribute name
*/
- protected static String toBeanAttributeName(TypedElementName method,
+ protected static String toBeanAttributeName(TypedElementInfo method,
boolean isBeanStyleRequired) {
AtomicReference>> refAttrNames = new AtomicReference<>();
validateAndParseMethodName(method.elementName(), method.typeName().name(), isBeanStyleRequired, refAttrNames);
@@ -584,9 +585,9 @@ private void gatherAllAttributeNames(TypeInfo typeInfo) {
}
}
- for (TypedElementName method : typeInfo.elementInfo()) {
+ for (TypedElementInfo method : typeInfo.interestingElementInfo()) {
String beanAttributeName = toBeanAttributeName(method, beanStyleRequired);
- TypedElementName existing = map.get(beanAttributeName);
+ TypedElementInfo existing = map.get(beanAttributeName);
if (existing != null
&& isBooleanType(method.typeName().name())
&& method.elementName().startsWith("is")) {
@@ -629,16 +630,16 @@ && isBooleanType(method.typeName().name())
}
}
- private static void populateMap(Map map,
+ private static void populateMap(Map map,
TypeInfo typeInfo,
boolean isBeanStyleRequired) {
if (typeInfo.superTypeInfo().isPresent()) {
populateMap(map, typeInfo.superTypeInfo().get(), isBeanStyleRequired);
}
- for (TypedElementName method : typeInfo.elementInfo()) {
+ for (TypedElementInfo method : typeInfo.interestingElementInfo()) {
String beanAttributeName = toBeanAttributeName(method, isBeanStyleRequired);
- TypedElementName existing = map.get(beanAttributeName);
+ TypedElementInfo existing = map.get(beanAttributeName);
if (existing != null) {
if (!existing.typeName().equals(method.typeName())) {
throw new IllegalStateException(method + " cannot redefine types from super for " + beanAttributeName);
@@ -683,7 +684,7 @@ private static TypeName toCtorBuilderAcceptTypeName(TypeInfo typeInfo,
return typeInfo.typeName();
}
- return (parentAnnotationTypeName != null && typeInfo.elementInfo().isEmpty()
+ return (parentAnnotationTypeName != null && typeInfo.interestingElementInfo().isEmpty()
? typeInfo.superTypeInfo().orElseThrow().typeName() : typeInfo.typeName());
}
diff --git a/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/BuilderTypeTools.java b/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/BuilderTypeTools.java
index 71c872e9c7f..35521795c00 100644
--- a/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/BuilderTypeTools.java
+++ b/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/BuilderTypeTools.java
@@ -58,8 +58,8 @@
import io.helidon.common.types.TypeInfoDefault;
import io.helidon.common.types.TypeName;
import io.helidon.common.types.TypeNameDefault;
-import io.helidon.common.types.TypedElementName;
-import io.helidon.common.types.TypedElementNameDefault;
+import io.helidon.common.types.TypedElementInfo;
+import io.helidon.common.types.TypedElementInfoDefault;
// this is really ok!
import com.sun.source.util.TreePath;
@@ -109,17 +109,15 @@ public Optional createBuilderTypeInfo(TypeName annotationTypeName,
throw new IllegalStateException(msg);
}
- Collection elementInfo = toElementInfo(element, processingEnv, true, wantDefaultMethods);
- Collection otherElementInfo = toElementInfo(element, processingEnv, false, wantDefaultMethods);
- Set modifierNames = toModifierNames(element.getModifiers()).stream()
- .map(String::toUpperCase)
- .collect(Collectors.toSet());
+ Collection elementInfo = toElementInfo(element, processingEnv, true, wantDefaultMethods);
+ Collection otherElementInfo = toElementInfo(element, processingEnv, false, wantDefaultMethods);
+ Set modifierNames = toModifierNames(element.getModifiers());
return Optional.of(TypeInfoDefault.builder()
.typeName(typeName)
.typeKind(String.valueOf(element.getKind()))
.annotations(
createAnnotationAndValueListFromElement(element, processingEnv.getElementUtils()))
- .elementInfo(elementInfo)
+ .interestingElementInfo(elementInfo)
.otherElementInfo(otherElementInfo)
.referencedTypeNamesToAnnotations(
toReferencedTypeNamesAndAnnotations(
@@ -134,7 +132,7 @@ public Optional createBuilderTypeInfo(TypeName annotationTypeName,
public Optional createTypeInfo(TypeElement element,
TypeMirror mirror,
ProcessingEnvironment processingEnv,
- Predicate isOneWeCareAbout) {
+ Predicate isOneWeCareAbout) {
return toTypeInfo(element, mirror, processingEnv, isOneWeCareAbout);
}
@@ -178,12 +176,12 @@ static Map> toMetaAnnotations(Collection> toReferencedTypeNamesAndAnnotations(ProcessingEnvironment processingEnv,
TypeName typeName,
- Collection... refs) {
+ Collection... refs) {
Map> result = new LinkedHashMap<>();
- for (Collection ref : refs) {
- for (TypedElementName typedElementName : ref) {
- collectReferencedTypeNames(result, processingEnv, typeName, List.of(typedElementName.typeName()));
- collectReferencedTypeNames(result, processingEnv, typeName, typedElementName.typeName().typeArguments());
+ for (Collection ref : refs) {
+ for (TypedElementInfo typedElementInfo : ref) {
+ collectReferencedTypeNames(result, processingEnv, typeName, List.of(typedElementInfo.typeName()));
+ collectReferencedTypeNames(result, processingEnv, typeName, typedElementInfo.typeName().typeArguments());
}
}
return result;
@@ -208,7 +206,7 @@ private void collectReferencedTypeNames(Map>
}
/**
- * Translation the arguments to a collection of {@link io.helidon.common.types.TypedElementName}'s.
+ * Translation the arguments to a collection of {@link TypedElementInfo}'s.
*
* @param element the typed element (i.e., class)
* @param processingEnv the processing env
@@ -216,7 +214,7 @@ private void collectReferencedTypeNames(Map>
* @param wantDefaultMethods true to process {@code default} methods
* @return the collection of typed elements
*/
- private Collection toElementInfo(TypeElement element,
+ private Collection toElementInfo(TypeElement element,
ProcessingEnvironment processingEnv,
boolean wantWhatWeCanAccept,
boolean wantDefaultMethods) {
@@ -224,7 +222,7 @@ private Collection toElementInfo(TypeElement element,
.filter(it -> it.getKind() == ElementKind.METHOD)
.map(ExecutableElement.class::cast)
.filter(it -> (wantWhatWeCanAccept == canAccept(it, wantDefaultMethods)))
- .map(it -> createTypedElementNameFromElement(it, processingEnv.getElementUtils()))
+ .map(it -> createTypedElementInfoFromElement(it, processingEnv.getElementUtils()))
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
@@ -288,14 +286,14 @@ private Optional toBuilderTypeInfo(TypeName annotationTypeName,
* @param mirror the type mirror for the element being processed
* @param processingEnv the processing environment
* @param isOneWeCareAbout the predicate filter to determine whether the element is of interest, and therefore should be
- * included in {@link TypeInfo#elementInfo()}. Otherwise, if the predicate indicates it is not of
+ * included in {@link TypeInfo#interestingElementInfo()}. Otherwise, if the predicate indicates it is not of
* interest then the method will be placed under {@link TypeInfo#otherElementInfo()} instead
* @return the type info associated with the arguments being processed, or empty if not able to process the type
*/
static Optional toTypeInfo(TypeElement element,
TypeMirror mirror,
ProcessingEnvironment processingEnv,
- Predicate isOneWeCareAbout) {
+ Predicate isOneWeCareAbout) {
TypeName fqTypeName = createTypeNameFromMirror(mirror).orElseThrow();
if (fqTypeName.name().equals(Object.class.getName())) {
return Optional.empty();
@@ -317,10 +315,10 @@ static Optional toTypeInfo(TypeElement element,
createAnnotationAndValueSet(elementUtils.getTypeElement(genericTypeName.name()));
Map> referencedAnnotations =
new LinkedHashMap<>(toMetaAnnotations(annotations, processingEnv));
- List elementsWeCareAbout = new ArrayList<>();
- List otherElements = new ArrayList<>();
+ List elementsWeCareAbout = new ArrayList<>();
+ List otherElements = new ArrayList<>();
element.getEnclosedElements().stream()
- .map(it -> createTypedElementNameFromElement(it, elementUtils))
+ .map(it -> createTypedElementInfoFromElement(it, elementUtils))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(it -> {
@@ -339,7 +337,7 @@ static Optional toTypeInfo(TypeElement element,
.annotations(annotations)
.referencedTypeNamesToAnnotations(referencedAnnotations)
.modifierNames(toModifierNames(element.getModifiers()))
- .elementInfo(elementsWeCareAbout)
+ .interestingElementInfo(elementsWeCareAbout)
.otherElementInfo(otherElements);
// add all of the element's and parameters to the references annotation set
@@ -356,7 +354,7 @@ static Optional toTypeInfo(TypeElement element,
.filter(t -> !t.generic())
.forEach(allInterestingTypeNames::add);
it.parameterArguments().stream()
- .map(TypedElementName::typeName)
+ .map(TypedElementInfo::typeName)
.map(TypeName::genericTypeName)
.filter(t -> !isBuiltInJavaType(t))
.filter(t -> !t.generic())
@@ -706,19 +704,7 @@ public static Map extractValues(Map extends ExecutableElement,
}
/**
- * Extracts the singular {@code value()} value. Return value will always be non-null.
- *
- * @param am the annotation mirror
- * @param elements the elements
- * @return the extracted values
- */
- public static String extractValue(AnnotationMirror am,
- Elements elements) {
- return Objects.requireNonNull(extractValues(elements.getElementValuesWithDefaults(am)).get("value"));
- }
-
- /**
- * Creates an instance of a {@link io.helidon.common.types.TypedElementName} given its type and variable element from
+ * Creates an instance of a {@link TypedElementInfo} given its type and variable element from
* annotation processing. If the passed in element is not a {@link TypeInfo#KIND_FIELD}, {@link TypeInfo#KIND_METHOD},
* {@link TypeInfo#KIND_CONSTRUCTOR}, or {@link TypeInfo#KIND_PARAMETER} then this method may return empty.
*
@@ -726,13 +712,12 @@ public static String extractValue(AnnotationMirror am,
* @param elements the elements
* @return the created instance
*/
- public static Optional createTypedElementNameFromElement(Element v,
+ public static Optional createTypedElementInfoFromElement(Element v,
Elements elements) {
TypeName type = createTypeNameFromElement(v).orElse(null);
TypeMirror typeMirror = null;
String defaultValue = null;
- List params = List.of();
- List componentTypeNames = List.of();
+ List params = List.of();
List elementTypeAnnotations = List.of();
Set modifierNames = v.getModifiers().stream()
.map(Modifier::toString)
@@ -742,7 +727,7 @@ public static Optional createTypedElementNameFromElement(Eleme
ExecutableElement ee = (ExecutableElement) v;
typeMirror = Objects.requireNonNull(ee.getReturnType());
params = ee.getParameters().stream()
- .map(it -> createTypedElementNameFromElement(it, elements).orElseThrow())
+ .map(it -> createTypedElementInfoFromElement(it, elements).orElseThrow())
.collect(Collectors.toList());
AnnotationValue annotationValue = ee.getDefaultValue();
defaultValue = (annotationValue == null) ? null
@@ -762,20 +747,13 @@ public static Optional createTypedElementNameFromElement(Eleme
type = createTypeNameFromMirror(typeMirror).orElse(createFromGenericDeclaration(typeMirror.toString()));
}
if (typeMirror instanceof DeclaredType) {
- List extends TypeMirror> args = ((DeclaredType) typeMirror).getTypeArguments();
- componentTypeNames = args.stream()
- .map(BuilderTypeTools::createTypeNameFromMirror)
- .filter(Optional::isPresent)
- .map(Optional::orElseThrow)
- .collect(Collectors.toList());
elementTypeAnnotations =
createAnnotationAndValueListFromElement(((DeclaredType) typeMirror).asElement(), elements);
}
}
- TypedElementNameDefault.Builder builder = TypedElementNameDefault.builder()
+ TypedElementInfoDefault.Builder builder = TypedElementInfoDefault.builder()
.typeName(type)
- .componentTypeNames(componentTypeNames)
.elementName(v.getSimpleName().toString())
.elementKind(v.getKind().name())
.annotations(createAnnotationAndValueListFromElement(v, elements))
diff --git a/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/DefaultBuilderCreatorProvider.java b/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/DefaultBuilderCreatorProvider.java
index d97a4a1cdec..33d45efda7b 100644
--- a/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/DefaultBuilderCreatorProvider.java
+++ b/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/DefaultBuilderCreatorProvider.java
@@ -47,7 +47,7 @@
import io.helidon.common.types.TypeInfo;
import io.helidon.common.types.TypeName;
import io.helidon.common.types.TypeNameDefault;
-import io.helidon.common.types.TypedElementName;
+import io.helidon.common.types.TypedElementInfo;
import io.helidon.config.metadata.ConfiguredOption;
import static io.helidon.builder.processor.tools.BodyContext.TAG_META_PROPS;
@@ -127,7 +127,7 @@ private void assertNoDuplicateSingularNames(TypeInfo typeInfo) {
Set names = new LinkedHashSet<>();
Set duplicateNames = new LinkedHashSet<>();
- typeInfo.elementInfo().stream()
+ typeInfo.interestingElementInfo().stream()
.map(DefaultBuilderCreatorProvider::nameOf)
.forEach(name -> {
if (!names.add(name)) {
@@ -342,7 +342,7 @@ protected void appendFields(StringBuilder builder,
}
for (int i = 0; i < ctx.allTypeInfos().size(); i++) {
- TypedElementName method = ctx.allTypeInfos().get(i);
+ TypedElementInfo method = ctx.allTypeInfos().get(i);
String beanAttributeName = ctx.allAttributeNames().get(i);
appendAnnotations(builder, method.annotations(), "\t");
builder.append("\tprivate ");
@@ -621,7 +621,7 @@ protected void appendVisitAttributes(StringBuilder builder,
// void visit(String key, Object value, Object userDefinedCtx, Class> type, Class>... typeArgument);
int i = 0;
for (String attrName : ctx.allAttributeNames()) {
- TypedElementName method = ctx.allTypeInfos().get(i);
+ TypedElementInfo method = ctx.allTypeInfos().get(i);
TypeName typeName = method.typeName();
List typeArgs = method.typeName().typeArguments().stream()
.map(this::normalize)
@@ -810,7 +810,7 @@ protected String toConfigKey(String name,
*/
protected void maybeAppendSingularSetter(StringBuilder builder,
BodyContext ctx,
- TypedElementName method,
+ TypedElementInfo method,
String beanAttributeName,
boolean isList, boolean isMap, boolean isSet) {
String singularVal = toValue(Singular.class, method, false, false).orElse(null);
@@ -843,7 +843,7 @@ protected static String maybeSingularFormOf(String beanAttributeName) {
* @param elem the element
* @return the (singular) name of the element
*/
- protected static String nameOf(TypedElementName elem) {
+ protected static String nameOf(TypedElementInfo elem) {
return AnnotationAndValueDefault.findFirst(Singular.class, elem.annotations())
.flatMap(AnnotationAndValue::value)
.filter(BuilderTypeTools::hasNonBlankValue)
@@ -863,7 +863,7 @@ protected void appendSetter(StringBuilder mainBuilder,
BodyContext ctx,
String beanAttributeName,
String methodName,
- TypedElementName method) {
+ TypedElementInfo method) {
appendSetter(mainBuilder, ctx, beanAttributeName, methodName, method, true, "");
}
@@ -871,7 +871,7 @@ private void appendSetter(StringBuilder mainBuilder,
BodyContext ctx,
String beanAttributeName,
String methodName,
- TypedElementName method,
+ TypedElementInfo method,
boolean doClear,
String prefixName) {
TypeName typeName = method.typeName();
@@ -954,7 +954,7 @@ private void appendSetter(StringBuilder mainBuilder,
protected void appendDirectNonOptionalSetter(StringBuilder builder,
BodyContext ctx,
String beanAttributeName,
- TypedElementName method,
+ TypedElementInfo method,
String methodName,
TypeName genericType) {
GenerateMethod.nonOptionalSetter(builder, ctx, beanAttributeName, method, methodName, genericType);
@@ -991,7 +991,7 @@ protected void appendAnnotations(StringBuilder builder,
* @param upLevelToCollection true if the generics should be "up leveled"
* @return the generic decl
*/
- protected static String toGenerics(TypedElementName method,
+ protected static String toGenerics(TypedElementInfo method,
boolean upLevelToCollection) {
return toGenerics(method.typeName(), upLevelToCollection);
}
@@ -1043,7 +1043,7 @@ protected static String toString(Collection coll,
* @param avoidBlanks flag indicating whether blank values should be ignored
* @return the default value, or empty if there is no default value applicable for the given arguments
*/
- protected static Optional toConfiguredOptionValue(TypedElementName method,
+ protected static Optional toConfiguredOptionValue(TypedElementInfo method,
boolean wantTypeElementDefaults,
boolean avoidBlanks) {
String val = toValue(ConfiguredOption.class, method, wantTypeElementDefaults, avoidBlanks).orElse(null);
@@ -1060,7 +1060,7 @@ protected static Optional toConfiguredOptionValue(TypedElementName metho
* @return the default value, or empty if there is no default value applicable for the given arguments
*/
protected static Optional toValue(Class extends Annotation> annoType,
- TypedElementName method,
+ TypedElementInfo method,
boolean wantTypeElementDefaults,
boolean avoidBlanks) {
if (wantTypeElementDefaults && method.defaultValue().isPresent()) {
@@ -1187,7 +1187,7 @@ private void appendBuilder(StringBuilder builder,
} else {
int i = 0;
for (String beanAttributeName : ctx.allAttributeNames()) {
- TypedElementName method = ctx.allTypeInfos().get(i);
+ TypedElementInfo method = ctx.allTypeInfos().get(i);
TypeName typeName = method.typeName();
boolean isList = typeName.isList();
boolean isMap = !isList && typeName.isMap();
@@ -1268,7 +1268,7 @@ private void appendBuilder(StringBuilder builder,
}
i = 0;
for (String beanAttributeName : ctx.allAttributeNames()) {
- TypedElementName method = ctx.allTypeInfos().get(i++);
+ TypedElementInfo method = ctx.allTypeInfos().get(i++);
TypeName typeName = method.typeName();
String getterName = method.elementName();
builder.append("\t\t\t").append(beanAttributeName).append("(");
@@ -1301,7 +1301,7 @@ private void appendBuilderBody(StringBuilder builder,
boolean hasFinal = false;
for (int i = 0; i < ctx.allAttributeNames().size(); i++) {
String beanAttributeName = ctx.allAttributeNames().get(i);
- TypedElementName method = ctx.allTypeInfos().get(i);
+ TypedElementInfo method = ctx.allTypeInfos().get(i);
TypeName typeName = method.typeName();
if (typeName.isList() || typeName.isMap() || typeName.isSet()) {
hasFinal = true;
@@ -1315,7 +1315,7 @@ private void appendBuilderBody(StringBuilder builder,
// then any other field
for (int i = 0; i < ctx.allAttributeNames().size(); i++) {
String beanAttributeName = ctx.allAttributeNames().get(i);
- TypedElementName method = ctx.allTypeInfos().get(i);
+ TypedElementInfo method = ctx.allTypeInfos().get(i);
TypeName typeName = method.typeName();
if (typeName.isList() || typeName.isMap() || typeName.isSet()) {
continue;
@@ -1341,7 +1341,7 @@ private void appendBuilderBody(StringBuilder builder,
private void addBuilderField(StringBuilder builder,
BodyContext ctx,
- TypedElementName method,
+ TypedElementInfo method,
TypeName type,
String beanAttributeName) {
GenerateJavadoc.builderField(builder, method);
@@ -1362,7 +1362,7 @@ private void addBuilderField(StringBuilder builder,
private void addCollectionField(StringBuilder builder,
BodyContext ctx,
- TypedElementName method,
+ TypedElementInfo method,
TypeName typeName,
String beanAttributeName) {
GenerateJavadoc.builderField(builder, method);
@@ -1474,7 +1474,7 @@ private void appendInterfaceBasedGetters(StringBuilder builder,
int i = 0;
for (String beanAttributeName : ctx.allAttributeNames()) {
- TypedElementName method = ctx.allTypeInfos().get(i);
+ TypedElementInfo method = ctx.allTypeInfos().get(i);
String extraPrefix = prefix + "\t";
appendAnnotations(builder, method.annotations(), extraPrefix);
builder.append(extraPrefix)
@@ -1537,7 +1537,7 @@ protected void appendCtorCodeBody(StringBuilder builder,
}
int i = 0;
for (String beanAttributeName : ctx.allAttributeNames()) {
- TypedElementName method = ctx.allTypeInfos().get(i++);
+ TypedElementInfo method = ctx.allTypeInfos().get(i++);
builder.append("\t\tthis.").append(beanAttributeName).append(" = ");
if (method.typeName().isList()) {
@@ -1573,7 +1573,7 @@ private void appendHashCodeAndEquals(StringBuilder builder,
builder.append("\t\tint hashCode = 1;\n");
}
List methods = new ArrayList<>();
- for (TypedElementName method : ctx.allTypeInfos()) {
+ for (TypedElementInfo method : ctx.allTypeInfos()) {
methods.add(method.elementName() + "()");
}
builder.append("\t\thashCode = 31 * hashCode + Objects.hash(").append(String.join(", ", methods)).append(");\n");
@@ -1595,7 +1595,7 @@ private void appendHashCodeAndEquals(StringBuilder builder,
} else {
builder.append("\t\tboolean equals = true;\n");
}
- for (TypedElementName method : ctx.allTypeInfos()) {
+ for (TypedElementInfo method : ctx.allTypeInfos()) {
String equalsClass = method.typeName().array() ? Arrays.class.getName() : "Objects";
builder.append("\t\tequals &= ").append(equalsClass).append(".equals(")
.append(method.elementName()).append("(), other.")
@@ -1630,7 +1630,7 @@ private void appendInnerToStringMethod(StringBuilder builder,
int i = 0;
for (String beanAttributeName : ctx.allAttributeNames()) {
- TypedElementName method = ctx.allTypeInfos().get(i++);
+ TypedElementInfo method = ctx.allTypeInfos().get(i++);
TypeName typeName = method.typeName();
builder.append("\t\tresult += \"").append(beanAttributeName).append("=\" + ");
@@ -1674,7 +1674,7 @@ private void appendInnerToStringMethod(StringBuilder builder,
}
private void appendDefaultValueAssignment(StringBuilder builder,
- TypedElementName method,
+ TypedElementInfo method,
String defaultVal) {
TypeName type = method.typeName();
boolean isOptional = type.isOptional();
@@ -1714,7 +1714,7 @@ private void appendDefaultValueAssignment(StringBuilder builder,
private void appendOverridesOfDefaultValues(StringBuilder builder,
BodyContext ctx) {
- for (TypedElementName method : ctx.typeInfo().elementInfo()) {
+ for (TypedElementInfo method : ctx.typeInfo().interestingElementInfo()) {
String beanAttributeName = toBeanAttributeName(method, ctx.beanStyleRequired());
if (!ctx.allAttributeNames().contains(beanAttributeName)) {
// candidate for override...
@@ -1734,7 +1734,7 @@ private String superValue(Optional optSuperTypeInfo,
return null;
}
TypeInfo superTypeInfo = optSuperTypeInfo.get();
- Optional method = superTypeInfo.elementInfo().stream()
+ Optional method = superTypeInfo.interestingElementInfo().stream()
.filter(it -> toBeanAttributeName(it, isBeanStyleRequired).equals(elemName))
.findFirst();
if (method.isPresent()) {
@@ -1751,7 +1751,7 @@ private String superValue(Optional optSuperTypeInfo,
private void appendDefaultOverride(StringBuilder builder,
String attrName,
- TypedElementName method,
+ TypedElementInfo method,
String override) {
builder.append("\t\t\t").append(attrName).append("(");
appendDefaultValueAssignment(builder, method, override);
@@ -1771,7 +1771,7 @@ private void appendCustomMapOf(StringBuilder builder) {
}
private String mapOf(String attrName,
- TypedElementName method,
+ TypedElementInfo method,
AtomicBoolean needsCustomMapOf) {
Optional extends AnnotationAndValue> configuredOptions = AnnotationAndValueDefault
.findFirst(ConfiguredOption.class, method.annotations());
diff --git a/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/GenerateJavadoc.java b/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/GenerateJavadoc.java
index a1ad7a40b49..b3f45b2ef28 100644
--- a/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/GenerateJavadoc.java
+++ b/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/GenerateJavadoc.java
@@ -17,7 +17,7 @@
package io.helidon.builder.processor.tools;
import io.helidon.common.types.TypeName;
-import io.helidon.common.types.TypedElementName;
+import io.helidon.common.types.TypedElementInfo;
final class GenerateJavadoc {
private GenerateJavadoc() {
@@ -106,7 +106,7 @@ static void updateConsumer(StringBuilder builder) {
}
static void builderField(StringBuilder builder,
- TypedElementName method) {
+ TypedElementInfo method) {
builder.append("\t\t/**\n" + "\t\t * Field value for {@code ")
.append(method)
.append("()}.\n\t\t */\n");
diff --git a/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/GenerateMethod.java b/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/GenerateMethod.java
index 911c13d0254..99d6774910d 100644
--- a/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/GenerateMethod.java
+++ b/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/GenerateMethod.java
@@ -21,7 +21,7 @@
import java.util.Optional;
import io.helidon.common.types.TypeName;
-import io.helidon.common.types.TypedElementName;
+import io.helidon.common.types.TypedElementInfo;
final class GenerateMethod {
static final String SINGULAR_PREFIX = "add";
@@ -50,7 +50,7 @@ static String builderMethods(StringBuilder builder,
static void stringToCharSetter(StringBuilder builder,
BodyContext ctx,
String beanAttributeName,
- TypedElementName method,
+ TypedElementInfo method,
String methodName) {
GenerateJavadoc.setter(builder, beanAttributeName);
builder.append("\t\tpublic ").append(ctx.genericBuilderAliasDecl()).append(" ").append(methodName)
@@ -76,7 +76,7 @@ static void internalMetaAttributes(StringBuilder builder) {
static void nonOptionalSetter(StringBuilder builder,
BodyContext ctx,
String beanAttributeName,
- TypedElementName method,
+ TypedElementInfo method,
String methodName,
TypeName genericType) {
GenerateJavadoc.setter(builder, beanAttributeName);
@@ -102,7 +102,7 @@ static void nonOptionalSetter(StringBuilder builder,
static void singularSetter(StringBuilder builder,
BodyContext ctx,
- TypedElementName method,
+ TypedElementInfo method,
String beanAttributeName,
char[] methodName) {
TypeName typeName = method.typeName();
@@ -209,7 +209,7 @@ private static TypeName mapValueTypeNameOf(TypeName typeName) {
return (typeName.isMap() && typeName.typeArguments().size() > 1) ? typeName.typeArguments().get(1) : null;
}
- private static String toGenericsDecl(TypedElementName method,
+ private static String toGenericsDecl(TypedElementInfo method,
boolean useSingluarMapValues,
TypeName mapValueType) {
List compTypeNames = method.typeName().typeArguments();
diff --git a/common/http/src/main/java/io/helidon/common/http/ClientResponseHeaders.java b/common/http/src/main/java/io/helidon/common/http/ClientResponseHeaders.java
index 7d9ffbace50..bdc6b99a58e 100644
--- a/common/http/src/main/java/io/helidon/common/http/ClientResponseHeaders.java
+++ b/common/http/src/main/java/io/helidon/common/http/ClientResponseHeaders.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2022, 2023 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.
@@ -24,6 +24,7 @@
import io.helidon.common.http.Http.DateTime;
import io.helidon.common.http.Http.HeaderValue;
+import io.helidon.common.media.type.ParserMode;
import static io.helidon.common.http.Http.Header.ACCEPT_PATCH;
import static io.helidon.common.http.Http.Header.EXPIRES;
@@ -36,12 +37,24 @@
public interface ClientResponseHeaders extends Headers {
/**
* Create a new instance from headers parsed from client response.
+ * Strict media type parsing mode is used for {@code Content-Type} header.
*
* @param responseHeaders client response headers
* @return immutable instance of client response HTTP headers
*/
static ClientResponseHeaders create(Headers responseHeaders) {
- return new ClientResponseHeadersImpl(responseHeaders);
+ return new ClientResponseHeadersImpl(responseHeaders, ParserMode.STRICT);
+ }
+
+ /**
+ * Create a new instance from headers parsed from client response.
+ *
+ * @param responseHeaders client response headers
+ * @param parserMode media type parsing mode
+ * @return immutable instance of client response HTTP headers
+ */
+ static ClientResponseHeaders create(Headers responseHeaders, ParserMode parserMode) {
+ return new ClientResponseHeadersImpl(responseHeaders, parserMode);
}
/**
diff --git a/common/http/src/main/java/io/helidon/common/http/ClientResponseHeadersImpl.java b/common/http/src/main/java/io/helidon/common/http/ClientResponseHeadersImpl.java
index 8197bb5e3b4..82e1a882bdc 100644
--- a/common/http/src/main/java/io/helidon/common/http/ClientResponseHeadersImpl.java
+++ b/common/http/src/main/java/io/helidon/common/http/ClientResponseHeadersImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2022, 2023 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.
@@ -18,13 +18,18 @@
import java.util.Iterator;
import java.util.List;
+import java.util.Optional;
import java.util.function.Supplier;
+import io.helidon.common.media.type.ParserMode;
+
class ClientResponseHeadersImpl implements ClientResponseHeaders {
private final Headers headers;
+ private final ParserMode parserMode;
- ClientResponseHeadersImpl(Headers headers) {
+ ClientResponseHeadersImpl(Headers headers, ParserMode parserMode) {
this.headers = headers;
+ this.parserMode = parserMode;
}
@Override
@@ -47,6 +52,16 @@ public Http.HeaderValue get(Http.HeaderName name) {
return headers.get(name);
}
+ @Override
+ public Optional contentType() {
+ if (parserMode == ParserMode.RELAXED) {
+ return contains(HeaderEnum.CONTENT_TYPE)
+ ? Optional.of(HttpMediaType.create(get(HeaderEnum.CONTENT_TYPE).value(), parserMode))
+ : Optional.empty();
+ }
+ return headers.contentType();
+ }
+
@Override
public int size() {
return headers.size();
diff --git a/common/http/src/main/java/io/helidon/common/http/DirectHandler.java b/common/http/src/main/java/io/helidon/common/http/DirectHandler.java
index 5d8017de0fe..c0a4f7d423c 100644
--- a/common/http/src/main/java/io/helidon/common/http/DirectHandler.java
+++ b/common/http/src/main/java/io/helidon/common/http/DirectHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2021, 2023 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.
@@ -16,6 +16,7 @@
package io.helidon.common.http;
+import java.lang.System.Logger.Level;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
@@ -29,11 +30,11 @@
*/
@FunctionalInterface
public interface DirectHandler {
+
/**
* Default handler will HTML encode the message (if any),
* use the default status code for the event type, and copy all headers configured.
*
- *
* @return default direct handler
*/
static DirectHandler defaultHandler() {
@@ -45,6 +46,7 @@ static DirectHandler defaultHandler() {
*
* This method should be used to return custom status, header and possible entity.
* If there is a need to handle more details, please redirect the client to a proper endpoint to handle them.
+ * This method shall not send an unsafe message back as an entity to avoid potential data leaks.
*
* @param request request as received with as much known information as possible
* @param eventType type of the event
@@ -58,6 +60,41 @@ default TransportResponse handle(TransportRequest request,
Http.Status defaultStatus,
ServerResponseHeaders responseHeaders,
Throwable thrown) {
+ return handle(request, eventType, defaultStatus, responseHeaders, thrown, null);
+ }
+
+ /**
+ * Handler of responses that bypass router.
+ *
+ * This method should be used to return custom status, header and possible entity.
+ * If there is a need to handle more details, please redirect the client to a proper endpoint to handle them.
+ * This method shall not send an unsafe message back as an entity to avoid potential data leaks.
+ *
+ * @param request request as received with as much known information as possible
+ * @param eventType type of the event
+ * @param defaultStatus default status expected to be returned
+ * @param responseHeaders headers to be added to response
+ * @param thrown throwable caught as part of processing with possible additional details about the reason of failure
+ * @param logger Possibly null logger to use for unsafe messages
+ * @return response to use to return to original request
+ */
+ default TransportResponse handle(TransportRequest request,
+ EventType eventType,
+ Http.Status defaultStatus,
+ ServerResponseHeaders responseHeaders,
+ Throwable thrown,
+ System.Logger logger) {
+ if (thrown instanceof RequestException re) {
+ if (re.safeMessage()) {
+ return handle(request, eventType, defaultStatus, responseHeaders, thrown.getMessage());
+ } else {
+ if (logger != null) {
+ logger.log(Level.ERROR, thrown);
+ }
+ return handle(request, eventType, defaultStatus, responseHeaders,
+ "Bad request, see server log for more information");
+ }
+ }
return handle(request, eventType, defaultStatus, responseHeaders, thrown.getMessage());
}
diff --git a/common/http/src/main/java/io/helidon/common/http/Http.java b/common/http/src/main/java/io/helidon/common/http/Http.java
index 1d60168cd5f..ed67d836b97 100644
--- a/common/http/src/main/java/io/helidon/common/http/Http.java
+++ b/common/http/src/main/java/io/helidon/common/http/Http.java
@@ -429,6 +429,11 @@ public static class Status {
* HTTP/1.1 documentation.
*/
public static final Status TEMPORARY_REDIRECT_307 = new Status(307, "Temporary Redirect", true);
+ /**
+ * 308 Permanent Redirect, see
+ * HTTP Status Code 308 documentation.
+ */
+ public static final Status PERMANENT_REDIRECT_308 = new Status(308, "Permanent Redirect", true);
/**
* 400 Bad Request, see
* HTTP/1.1 documentation.
diff --git a/common/http/src/main/java/io/helidon/common/http/Http1HeadersParser.java b/common/http/src/main/java/io/helidon/common/http/Http1HeadersParser.java
index b5e29d7383e..970147e9d60 100644
--- a/common/http/src/main/java/io/helidon/common/http/Http1HeadersParser.java
+++ b/common/http/src/main/java/io/helidon/common/http/Http1HeadersParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2022, 2023 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.
diff --git a/common/http/src/main/java/io/helidon/common/http/HttpMediaType.java b/common/http/src/main/java/io/helidon/common/http/HttpMediaType.java
index d7dfadaf817..b846ebb57a5 100644
--- a/common/http/src/main/java/io/helidon/common/http/HttpMediaType.java
+++ b/common/http/src/main/java/io/helidon/common/http/HttpMediaType.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 2023 Oracle and/or its affiliates.
+ * Copyright (c) 2023, 2023 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.
@@ -24,6 +24,7 @@
import io.helidon.common.media.type.MediaType;
import io.helidon.common.media.type.MediaTypes;
+import io.helidon.common.media.type.ParserMode;
/**
* Media type used in HTTP headers, in addition to the media type definition, these may contain additional
@@ -106,12 +107,24 @@ static HttpMediaType create(MediaType mediaType) {
/**
* Parse media type from the provided string.
+ * Strict media type parsing mode is used.
*
* @param mediaTypeString media type string
* @return HTTP media type parsed from the string
*/
static HttpMediaType create(String mediaTypeString) {
- return Builder.parse(mediaTypeString);
+ return Builder.parse(mediaTypeString, ParserMode.STRICT);
+ }
+
+ /**
+ * Parse media type from the provided string.
+ *
+ * @param mediaTypeString media type string
+ * @param parserMode media type parsing mode
+ * @return HTTP media type parsed from the string
+ */
+ static HttpMediaType create(String mediaTypeString, ParserMode parserMode) {
+ return Builder.parse(mediaTypeString, parserMode);
}
/**
@@ -310,7 +323,7 @@ MediaType mediaType() {
return mediaType;
}
- private static HttpMediaType parse(String mediaTypeString) {
+ private static HttpMediaType parse(String mediaTypeString, ParserMode parserMode) {
// text/plain; charset=UTF-8
Builder b = builder();
@@ -337,7 +350,7 @@ private static HttpMediaType parse(String mediaTypeString) {
}
}
} else {
- b.mediaType(MediaTypes.create(mediaTypeString));
+ b.mediaType(MediaTypes.create(mediaTypeString, parserMode));
}
return b.build();
}
diff --git a/common/http/src/main/java/io/helidon/common/http/RequestException.java b/common/http/src/main/java/io/helidon/common/http/RequestException.java
index 737a96a2425..0f2e1b4fa37 100644
--- a/common/http/src/main/java/io/helidon/common/http/RequestException.java
+++ b/common/http/src/main/java/io/helidon/common/http/RequestException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2022, 2023 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.
@@ -27,6 +27,7 @@ public class RequestException extends RuntimeException {
private final DirectHandler.TransportRequest transportRequest;
private final boolean keepAlive;
private final ServerResponseHeaders responseHeaders;
+ private final boolean safeMessage;
/**
* A new exception with a predefined status, even type.
@@ -41,6 +42,7 @@ protected RequestException(Builder builder) {
this.transportRequest = builder.request;
this.keepAlive = builder.keepAlive;
this.responseHeaders = builder.responseHeaders;
+ this.safeMessage = builder.safeMessage;
}
/**
@@ -97,6 +99,16 @@ public ServerResponseHeaders responseHeaders() {
return responseHeaders;
}
+ /**
+ * Safe message flag used to control which messages can be sent as
+ * part of a response and which should only be logged by the server.
+ *
+ * @return safe message flag
+ */
+ public boolean safeMessage() {
+ return safeMessage;
+ }
+
/**
* Fluent API builder for {@link RequestException}.
*/
@@ -108,6 +120,7 @@ public static class Builder implements io.helidon.common.Builder {
+ HttpMediaType.create("text");
+ },
+ "Cannot parse media type: text");
+ }
+
+ // Calling create method with "text" argument shall return "text/plain" in relaxed mode.
+ @Test
+ void parseInvalidTextInRelaxedMode() {
+ HttpMediaType type = HttpMediaType.create("text", ParserMode.RELAXED);
+ assertThat(type.text(), is("text/plain"));
+ }
+
}
diff --git a/common/media-type/src/main/java/io/helidon/common/media/type/MediaTypeImpl.java b/common/media-type/src/main/java/io/helidon/common/media/type/MediaTypeImpl.java
index 589beaa456f..311c49b3553 100644
--- a/common/media-type/src/main/java/io/helidon/common/media/type/MediaTypeImpl.java
+++ b/common/media-type/src/main/java/io/helidon/common/media/type/MediaTypeImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2023 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.
@@ -16,10 +16,25 @@
package io.helidon.common.media.type;
+import java.util.Optional;
+
record MediaTypeImpl(String type, String subtype, String text) implements MediaType {
- static MediaType parse(String fullType) {
+
+ private static final System.Logger LOGGER = System.getLogger(MediaTypeImpl.class.getName());
+
+ static MediaType parse(String fullType, ParserMode parserMode) {
int slashIndex = fullType.indexOf('/');
if (slashIndex < 1) {
+ if (parserMode == ParserMode.RELAXED) {
+ Optional maybeRelaxedType = ParserMode.findRelaxedMediaType(fullType);
+ if (maybeRelaxedType.isPresent()) {
+ LOGGER.log(System.Logger.Level.DEBUG,
+ () -> String.format("Invalid media type value \"%s\" replaced with \"%s\"",
+ fullType,
+ maybeRelaxedType.get().text()));
+ return maybeRelaxedType.get();
+ }
+ }
throw new IllegalArgumentException("Cannot parse media type: " + fullType);
}
return new MediaTypeImpl(fullType.substring(0, slashIndex),
diff --git a/common/media-type/src/main/java/io/helidon/common/media/type/MediaTypes.java b/common/media-type/src/main/java/io/helidon/common/media/type/MediaTypes.java
index adcb2f37d0b..66fe780fdb1 100644
--- a/common/media-type/src/main/java/io/helidon/common/media/type/MediaTypes.java
+++ b/common/media-type/src/main/java/io/helidon/common/media/type/MediaTypes.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2019, 2023 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.
@@ -151,13 +151,26 @@ public static MediaType create(String type, String subtype) {
/**
* Create a new media type from the full media type string.
+ * Strict media type parsing mode is used.
*
* @param fullType media type string, such as {@code application/json}
* @return media type for the string
*/
public static MediaType create(String fullType) {
MediaTypeEnum types = MediaTypeEnum.find(fullType);
- return types == null ? MediaTypeImpl.parse(fullType) : types;
+ return types == null ? MediaTypeImpl.parse(fullType, ParserMode.STRICT) : types;
+ }
+
+ /**
+ * Create a new media type from the full media type string.
+ *
+ * @param fullType media type string, such as {@code application/json}
+ * @param parserMode media type parsing mode
+ * @return media type for the string
+ */
+ public static MediaType create(String fullType, ParserMode parserMode) {
+ MediaTypeEnum types = MediaTypeEnum.find(fullType);
+ return types == null ? MediaTypeImpl.parse(fullType, parserMode) : types;
}
/**
diff --git a/common/media-type/src/main/java/io/helidon/common/media/type/ParserMode.java b/common/media-type/src/main/java/io/helidon/common/media/type/ParserMode.java
new file mode 100644
index 00000000000..8f3dfcdd4cc
--- /dev/null
+++ b/common/media-type/src/main/java/io/helidon/common/media/type/ParserMode.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2023 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.common.media.type;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * Media type parsing mode.
+ */
+public enum ParserMode {
+
+ /**
+ * Strict mode (default).
+ * Media type must match known name.
+ */
+ STRICT,
+ /**
+ * Relaxed mode.
+ * Apply additional rules to identify unknown media types.
+ */
+ RELAXED;
+
+ // Relaxed media types mapping
+ private static final Map RELAXED_TYPES = Map.of(
+ "text", MediaTypes.TEXT_PLAIN // text -> text/plain
+ );
+
+ /**
+ * Find relaxed media type mapping for provided value.
+ *
+ * @param value source media type value
+ * @return mapped media type value or {@code Optional.empty()}
+ * when no mapping for given value exists
+ */
+ static Optional findRelaxedMediaType(String value) {
+ Objects.requireNonNull(value);
+ MediaType relaxedValue = RELAXED_TYPES.get(value);
+ return relaxedValue != null ? Optional.of(relaxedValue) : Optional.empty();
+ }
+
+}
diff --git a/common/types/src/main/java/io/helidon/common/types/AnnotationAndValueDefault.java b/common/types/src/main/java/io/helidon/common/types/AnnotationAndValueDefault.java
index cc772071ac5..059655480fd 100644
--- a/common/types/src/main/java/io/helidon/common/types/AnnotationAndValueDefault.java
+++ b/common/types/src/main/java/io/helidon/common/types/AnnotationAndValueDefault.java
@@ -31,7 +31,7 @@ public class AnnotationAndValueDefault implements AnnotationAndValue, Comparable
private final Map values;
/**
- * Ctor.
+ * Constructor taking the result of the fluent builder.
*
* @param b the builder
* @see #builder()
@@ -230,12 +230,11 @@ public int compareTo(AnnotationAndValue other) {
*/
public static class Builder implements io.helidon.common.Builder {
private final Map values = new LinkedHashMap<>();
-
private TypeName typeName;
private String value;
/**
- * Default ctor.
+ * Default fluent builder constructor.
*/
protected Builder() {
}
diff --git a/common/types/src/main/java/io/helidon/common/types/TypeInfo.java b/common/types/src/main/java/io/helidon/common/types/TypeInfo.java
index ecc7406c645..93cd8017d10 100644
--- a/common/types/src/main/java/io/helidon/common/types/TypeInfo.java
+++ b/common/types/src/main/java/io/helidon/common/types/TypeInfo.java
@@ -16,6 +16,8 @@
package io.helidon.common.types;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -28,35 +30,35 @@ public interface TypeInfo {
/**
* The {@code public} modifier.
*/
- String MODIFIER_PUBLIC = "PUBLIC";
+ String MODIFIER_PUBLIC = "public";
/**
* The {@code protected} modifier.
*/
- String MODIFIER_PROTECTED = "PROTECTED";
+ String MODIFIER_PROTECTED = "protected";
/**
* The {@code private} modifier.
*/
- String MODIFIER_PRIVATE = "PRIVATE";
+ String MODIFIER_PRIVATE = "private";
/**
* The {@code abstract} modifier.
*/
- String MODIFIER_ABSTRACT = "ABSTRACT";
+ String MODIFIER_ABSTRACT = "abstract";
/**
* The {@code default} modifier.
*/
- String MODIFIER_DEFAULT = "DEFAULT";
+ String MODIFIER_DEFAULT = "default";
/**
* The {@code static} modifier.
*/
- String MODIFIER_STATIC = "STATIC";
+ String MODIFIER_STATIC = "static";
/**
* The {@code sealed} modifier.
*/
- String MODIFIER_SEALED = "SEALED";
+ String MODIFIER_SEALED = "sealed";
/**
* The {@code final} modifier.
*/
- String MODIFIER_FINAL = "FINAL";
+ String MODIFIER_FINAL = "final";
/**
@@ -146,7 +148,7 @@ public interface TypeInfo {
*
* @return the elements that make up the type that are relevant for processing
*/
- List elementInfo();
+ List interestingElementInfo();
/**
* The elements that make up this type that are considered "other", or being skipped because they are irrelevant to
@@ -154,7 +156,28 @@ public interface TypeInfo {
*
* @return the elements that still make up the type, but are otherwise deemed irrelevant for processing
*/
- List otherElementInfo();
+ List otherElementInfo();
+
+ /**
+ * Combines {@link #interestingElementInfo()} and {@link #otherElementInfo()} to form all typed element info belonging to this
+ * instance.
+ *
+ * @return all element info
+ */
+ default List allElementInfo() {
+ List interestingElementInfo = interestingElementInfo();
+ List otherElementInfo = otherElementInfo();
+
+ if (interestingElementInfo.isEmpty()) {
+ return otherElementInfo;
+ } else if (otherElementInfo.isEmpty()) {
+ return interestingElementInfo;
+ }
+
+ LinkedHashSet all = new LinkedHashSet<>(interestingElementInfo);
+ all.addAll(otherElementInfo);
+ return new ArrayList<>(all);
+ }
/**
* Any Map, List, Set, or method that has {@link TypeName#typeArguments()} will be analyzed and any type arguments will have
diff --git a/common/types/src/main/java/io/helidon/common/types/TypeInfoDefault.java b/common/types/src/main/java/io/helidon/common/types/TypeInfoDefault.java
index c3c46d4def3..10c714e6640 100644
--- a/common/types/src/main/java/io/helidon/common/types/TypeInfoDefault.java
+++ b/common/types/src/main/java/io/helidon/common/types/TypeInfoDefault.java
@@ -33,8 +33,8 @@ public class TypeInfoDefault implements TypeInfo {
private final TypeName typeName;
private final String typeKind;
private final List annotations;
- private final List elementInfo;
- private final List otherElementInfo;
+ private final List elementInfo;
+ private final List otherElementInfo;
private final Map referencedModuleNames;
private final Map> referencedTypeNamesToAnnotations;
private final TypeInfo superTypeInfo;
@@ -85,12 +85,12 @@ public List annotations() {
}
@Override
- public List elementInfo() {
+ public List interestingElementInfo() {
return elementInfo;
}
@Override
- public List otherElementInfo() {
+ public List otherElementInfo() {
return otherElementInfo;
}
@@ -131,7 +131,7 @@ public String toString() {
*/
protected String toStringInner() {
return "typeName=" + typeName()
- + ", elementInfo=" + elementInfo()
+ + ", elementInfo=" + allElementInfo()
+ ", annotations=" + annotations()
+ ", superTypeInfo=" + superTypeInfo()
+ ", modifierNames=" + modifierNames();
@@ -142,15 +142,14 @@ protected String toStringInner() {
*/
public static class Builder implements io.helidon.common.Builder {
private final List annotations = new ArrayList<>();
- private final List elementInfo = new ArrayList<>();
- private final List otherElementInfo = new ArrayList<>();
+ private final List elementInfo = new ArrayList<>();
+ private final List otherElementInfo = new ArrayList<>();
private final Map referencedModuleNames = new LinkedHashMap<>();
private final Map> referencedTypeNamesToAnnotations = new LinkedHashMap<>();
private final List interfaceTypeInfo = new ArrayList<>();
private final Set modifierNames = new LinkedHashSet<>();
private TypeName typeName;
private String typeKind;
-
private TypeInfo superTypeInfo;
/**
@@ -217,12 +216,12 @@ public Builder addAnnotation(AnnotationAndValue val) {
}
/**
- * Sets the elementInfo to val.
+ * Sets the interestingElementInfo to val.
*
* @param val the value
* @return this fluent builder
*/
- public Builder elementInfo(Collection val) {
+ public Builder interestingElementInfo(Collection val) {
Objects.requireNonNull(val);
this.elementInfo.clear();
this.elementInfo.addAll(val);
@@ -230,12 +229,12 @@ public Builder elementInfo(Collection val) {
}
/**
- * Adds a single elementInfo val.
+ * Adds a single interestingElementInfo val.
*
* @param val the value
* @return this fluent builder
*/
- public Builder addElementInfo(TypedElementName val) {
+ public Builder addInterestingElementInfo(TypedElementInfo val) {
Objects.requireNonNull(val);
elementInfo.add(val);
return identity();
@@ -247,7 +246,7 @@ public Builder addElementInfo(TypedElementName val) {
* @param val the value
* @return this fluent builder
*/
- public Builder otherElementInfo(Collection val) {
+ public Builder otherElementInfo(Collection val) {
Objects.requireNonNull(val);
this.otherElementInfo.clear();
this.otherElementInfo.addAll(val);
@@ -260,7 +259,7 @@ public Builder otherElementInfo(Collection val) {
* @param val the value
* @return this fluent builder
*/
- public Builder addOtherElementInfo(TypedElementName val) {
+ public Builder addOtherElementInfo(TypedElementInfo val) {
Objects.requireNonNull(val);
otherElementInfo.add(val);
return identity();
diff --git a/common/types/src/main/java/io/helidon/common/types/TypedElementName.java b/common/types/src/main/java/io/helidon/common/types/TypedElementInfo.java
similarity index 91%
rename from common/types/src/main/java/io/helidon/common/types/TypedElementName.java
rename to common/types/src/main/java/io/helidon/common/types/TypedElementInfo.java
index 298c17b4361..e78903faf8f 100644
--- a/common/types/src/main/java/io/helidon/common/types/TypedElementName.java
+++ b/common/types/src/main/java/io/helidon/common/types/TypedElementInfo.java
@@ -24,7 +24,7 @@
* Provides a way to describe a {@link TypeInfo#KIND_FIELD}, {@link TypeInfo#KIND_METHOD}, or {@link TypeInfo#KIND_PARAMETER}
* of a method.
*/
-public interface TypedElementName {
+public interface TypedElementInfo {
/**
* The type name for the element (e.g., java.util.List). If the element is a method, then this is the return type of
* the method.
@@ -70,13 +70,6 @@ public interface TypedElementName {
*/
List elementTypeAnnotations();
- /**
- * Returns the component type names describing the element.
- *
- * @return the component type names of the element
- */
- List componentTypeNames();
-
/**
* Element modifiers.
*
@@ -99,6 +92,6 @@ public interface TypedElementName {
*
* @return the list of parameters belonging to this method if applicable
*/
- List parameterArguments();
+ List parameterArguments();
}
diff --git a/common/types/src/main/java/io/helidon/common/types/TypedElementNameDefault.java b/common/types/src/main/java/io/helidon/common/types/TypedElementInfoDefault.java
similarity index 87%
rename from common/types/src/main/java/io/helidon/common/types/TypedElementNameDefault.java
rename to common/types/src/main/java/io/helidon/common/types/TypedElementInfoDefault.java
index 0e69011daba..1bee6929ded 100644
--- a/common/types/src/main/java/io/helidon/common/types/TypedElementNameDefault.java
+++ b/common/types/src/main/java/io/helidon/common/types/TypedElementInfoDefault.java
@@ -28,12 +28,11 @@
import static io.helidon.common.types.TypeNameDefault.create;
/**
- * Default implementation for {@link io.helidon.common.types.TypedElementName}.
+ * Default implementation for {@link TypedElementInfo}.
*/
@SuppressWarnings("unused")
-public class TypedElementNameDefault implements TypedElementName {
+public class TypedElementInfoDefault implements TypedElementInfo {
private final TypeName typeName;
- private final List componentTypeNames;
private final String elementName;
private final String elementKind;
private final String defaultValue;
@@ -41,7 +40,7 @@ public class TypedElementNameDefault implements TypedElementName {
private final List elementTypeAnnotations;
private final Set modifierNames;
private final TypeName enclosingTypeName;
- private final List parameters;
+ private final List parameters;
/**
* Constructor taking the fluent builder.
@@ -49,9 +48,8 @@ public class TypedElementNameDefault implements TypedElementName {
* @param b the builder
* @see #builder()
*/
- protected TypedElementNameDefault(Builder b) {
+ protected TypedElementInfoDefault(Builder b) {
this.typeName = b.typeName;
- this.componentTypeNames = List.copyOf(b.componentTypeNames);
this.elementName = b.elementName;
this.elementKind = b.elementKind;
this.defaultValue = b.defaultValue;
@@ -92,11 +90,6 @@ public List elementTypeAnnotations() {
return elementTypeAnnotations;
}
- @Override
- public List componentTypeNames() {
- return componentTypeNames;
- }
-
@Override
public Set modifierNames() {
return modifierNames;
@@ -108,7 +101,7 @@ public Optional enclosingTypeName() {
}
@Override
- public List parameterArguments() {
+ public List parameterArguments() {
return parameters;
}
@@ -119,11 +112,11 @@ public int hashCode() {
@Override
public boolean equals(Object another) {
- if (!(another instanceof TypedElementName)) {
+ if (!(another instanceof TypedElementInfo)) {
return false;
}
- TypedElementName other = (TypedElementName) another;
+ TypedElementInfo other = (TypedElementInfo) another;
return Objects.equals(typeName(), other.typeName())
&& Objects.equals(elementName(), other.elementName())
&& Objects.equals(elementTypeKind(), other.elementTypeKind())
@@ -163,7 +156,7 @@ public String toDeclaration() {
}
/**
- * Creates a builder for {@link io.helidon.common.types.TypedElementName}.
+ * Creates a builder for {@link TypedElementInfo}.
*
* @return a fluent builder
*/
@@ -176,11 +169,10 @@ public static Builder builder() {
* The fluent builder.
*/
public static class Builder {
- private final List componentTypeNames = new ArrayList<>();
private final List annotations = new ArrayList<>();
private final List elementTypeAnnotations = new ArrayList<>();
private final Set modifierNames = new LinkedHashSet<>();
- private final List parameters = new ArrayList<>();
+ private final List parameters = new ArrayList<>();
private TypeName typeName;
private String elementName;
@@ -216,19 +208,6 @@ public Builder typeName(Class> type) {
return typeName(create(type));
}
- /**
- * Set the component type names.
- *
- * @param val the component type values
- * @return this fluent builder
- */
- public Builder componentTypeNames(List val) {
- Objects.requireNonNull(val);
- this.componentTypeNames.clear();
- this.componentTypeNames.addAll(val);
- return this;
- }
-
/**
* Set the element name.
*
@@ -356,7 +335,7 @@ public Builder enclosingTypeName(Class> val) {
* @param val the parameter values
* @return this fluent builder
*/
- public Builder parameterArguments(List val) {
+ public Builder parameterArguments(List val) {
Objects.requireNonNull(val);
this.parameters.clear();
this.parameters.addAll(val);
@@ -369,7 +348,7 @@ public Builder parameterArguments(List val) {
* @param val the parameter value
* @return the fluent builder
*/
- public Builder addParameterArgument(TypedElementName val) {
+ public Builder addParameterArgument(TypedElementInfo val) {
Objects.requireNonNull(val);
this.parameters.add(val);
return this;
@@ -380,9 +359,9 @@ public Builder addParameterArgument(TypedElementName val) {
*
* @return the built instance
*/
- public TypedElementNameDefault build() {
+ public TypedElementInfoDefault build() {
Objects.requireNonNull(typeName);
- return new TypedElementNameDefault(this);
+ return new TypedElementInfoDefault(this);
}
}
diff --git a/common/types/src/test/java/io/helidon/common/types/TypedElementNameDefaultTest.java b/common/types/src/test/java/io/helidon/common/types/TypedElementInfoDefaultTest.java
similarity index 64%
rename from common/types/src/test/java/io/helidon/common/types/TypedElementNameDefaultTest.java
rename to common/types/src/test/java/io/helidon/common/types/TypedElementInfoDefaultTest.java
index 68e7c3ec1e8..4d179297f50 100644
--- a/common/types/src/test/java/io/helidon/common/types/TypedElementNameDefaultTest.java
+++ b/common/types/src/test/java/io/helidon/common/types/TypedElementInfoDefaultTest.java
@@ -16,74 +16,78 @@
package io.helidon.common.types;
+import java.util.List;
+
import org.junit.jupiter.api.Test;
import static io.helidon.common.types.TypeNameDefault.create;
import static io.helidon.common.types.TypeNameDefault.createFromTypeName;
import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
-class TypedElementNameDefaultTest {
+class TypedElementInfoDefaultTest {
@Test
void declarations() {
- assertThat(TypedElementNameDefault.builder()
+ assertThat(TypedElementInfoDefault.builder()
.elementName("arg")
.typeName(create(boolean.class))
.build().toString(),
is("boolean arg"));
- assertThat(TypedElementNameDefault.builder()
+ assertThat(TypedElementInfoDefault.builder()
.elementName("arg")
.typeName(create(byte.class))
.build().toString(),
is("byte arg"));
- assertThat(TypedElementNameDefault.builder()
+ assertThat(TypedElementInfoDefault.builder()
.elementName("arg")
.typeName(create(short.class))
.build().toString(),
is("short arg"));
- assertThat(TypedElementNameDefault.builder()
+ assertThat(TypedElementInfoDefault.builder()
.elementName("arg")
.typeName(create(int.class))
.build().toString(),
is("int arg"));
- assertThat(TypedElementNameDefault.builder()
+ assertThat(TypedElementInfoDefault.builder()
.elementName("arg")
.typeName(create(long.class))
.build().toString(),
is("long arg"));
- assertThat(TypedElementNameDefault.builder()
+ assertThat(TypedElementInfoDefault.builder()
.elementName("arg")
.typeName(create(char.class))
.build().toString(),
is("char arg"));
- assertThat(TypedElementNameDefault.builder()
+ assertThat(TypedElementInfoDefault.builder()
.elementName("arg")
.typeName(create(float.class))
.build().toString(),
is("float arg"));
- assertThat(TypedElementNameDefault.builder()
+ assertThat(TypedElementInfoDefault.builder()
.elementName("arg")
.typeName(create(double.class))
.build().toString(),
is("double arg"));
- assertThat(TypedElementNameDefault.builder()
+ assertThat(TypedElementInfoDefault.builder()
.elementName("arg")
.typeName(create(void.class))
.build().toString(),
is("void arg"));
- assertThat(TypedElementNameDefault.builder()
+ assertThat(TypedElementInfoDefault.builder()
.enclosingTypeName(createFromTypeName("MyClass"))
.elementName("hello")
.typeName(create(void.class))
.elementKind(TypeInfo.KIND_METHOD)
- .addParameterArgument(TypedElementNameDefault.builder()
+ .addParameterArgument(TypedElementInfoDefault.builder()
.elementName("arg1")
.typeName(create(String.class))
.elementKind(TypeInfo.KIND_PARAMETER)
.build())
- .addParameterArgument(TypedElementNameDefault.builder()
+ .addParameterArgument(TypedElementInfoDefault.builder()
.elementName("arg2")
.typeName(create(int.class))
.elementKind(TypeInfo.KIND_PARAMETER)
@@ -92,4 +96,37 @@ void declarations() {
is("MyClass::void hello(java.lang.String arg1, int arg2)"));
}
+ @Test
+ void allElementInfo() {
+ TypedElementInfo m1 = TypedElementInfoDefault.builder()
+ .typeName(getClass())
+ .elementKind(TypeInfo.KIND_METHOD)
+ .elementName("m1")
+ .build();
+ TypedElementInfo m2 = TypedElementInfoDefault.builder()
+ .typeName(getClass())
+ .elementKind(TypeInfo.KIND_METHOD)
+ .elementName("m2")
+ .build();
+
+ TypeInfo typeInfo = TypeInfoDefault.builder()
+ .addInterestingElementInfo(m1)
+ .build();
+ assertThat(typeInfo.allElementInfo(),
+ sameInstance(typeInfo.interestingElementInfo()));
+
+ typeInfo = TypeInfoDefault.builder()
+ .addOtherElementInfo(m1)
+ .build();
+ assertThat(typeInfo.allElementInfo(),
+ sameInstance(typeInfo.otherElementInfo()));
+
+ typeInfo = TypeInfoDefault.builder()
+ .addInterestingElementInfo(m1)
+ .otherElementInfo(List.of(m2, m1))
+ .build();
+ assertThat(typeInfo.allElementInfo(),
+ contains(m1, m2));
+ }
+
}
diff --git a/config/config-mp/src/main/java/io/helidon/config/mp/MpConfig.java b/config/config-mp/src/main/java/io/helidon/config/mp/MpConfig.java
index 09a635bdd56..4cae9f4b0ec 100644
--- a/config/config-mp/src/main/java/io/helidon/config/mp/MpConfig.java
+++ b/config/config-mp/src/main/java/io/helidon/config/mp/MpConfig.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2021 Oracle and/or its affiliates.
+ * Copyright (c) 2020, 2023 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.
@@ -16,7 +16,9 @@
package io.helidon.config.mp;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map;
import io.helidon.config.ConfigSources;
import io.helidon.config.OverrideSources;
@@ -48,29 +50,42 @@ public static io.helidon.config.Config toHelidonConfig(Config mpConfig) {
return (io.helidon.config.Config) mpConfig;
}
- // If the mpConfig is based on an SE config (such as when we use meta configuration)pom.xml
- // we must reuse that se config instance
- Iterator configSources = mpConfig.getConfigSources().iterator();
- ConfigSource first = configSources.hasNext() ? configSources.next() : null;
- if (!configSources.hasNext() && first instanceof MpHelidonConfigSource) {
- // we only have Helidon SE config as a source - let's just use it
- return ((MpHelidonConfigSource) first).unwrap();
+ if (mpConfig instanceof MpConfigImpl) {
+
+ // If the mpConfig is based on an SE config (such as when we use meta configuration)pom.xml
+ // we must reuse that se config instance
+ Iterator configSources = mpConfig.getConfigSources().iterator();
+ ConfigSource first = configSources.hasNext() ? configSources.next() : null;
+ if (!configSources.hasNext() && first instanceof MpHelidonConfigSource) {
+ // we only have Helidon SE config as a source - let's just use it
+ return ((MpHelidonConfigSource) first).unwrap();
+ }
+
+ // we use Helidon SE config to handle object mapping (and possible other mappers on classpath)
+ io.helidon.config.Config mapper = io.helidon.config.Config.builder()
+ .sources(ConfigSources.empty())
+ .overrides(OverrideSources.empty())
+ .disableEnvironmentVariablesSource()
+ .disableSystemPropertiesSource()
+ .disableParserServices()
+ .disableFilterServices()
+ .disableCaching()
+ .disableValueResolving()
+ .changesExecutor(command -> {
+ })
+ .build();
+
+ return new SeConfig(mapper, mpConfig);
}
- // we use Helidon SE config to handle object mapping (and possible other mappers on classpath)
- io.helidon.config.Config mapper = io.helidon.config.Config.builder()
- .sources(ConfigSources.empty())
- .overrides(OverrideSources.empty())
- .disableEnvironmentVariablesSource()
- .disableSystemPropertiesSource()
- .disableParserServices()
- .disableFilterServices()
- .disableCaching()
- .disableValueResolving()
- .changesExecutor(command -> {
- })
- .build();
+ // Generic Properties convert
+ Map propertyMap = new HashMap<>();
+ for (ConfigSource configSource : mpConfig.getConfigSources()) {
+ for (String propertyName : configSource.getPropertyNames()) {
+ propertyMap.putIfAbsent(propertyName, configSource.getValue(propertyName));
+ }
+ }
- return new SeConfig(mapper, mpConfig);
+ return io.helidon.config.Config.create(ConfigSources.create(propertyMap));
}
}
diff --git a/dependencies/pom.xml b/dependencies/pom.xml
index 5c95b762270..7ec97999fc8 100644
--- a/dependencies/pom.xml
+++ b/dependencies/pom.xml
@@ -53,8 +53,8 @@
2.3.33.21.722.3.0
- 17.5
- 17.1
+ 18.6
+ 18.32.9.01.54.131.1-jre
@@ -82,7 +82,7 @@
3.0.02.1.04.0.0
- 2.4.3.Final
+ 3.1.23.0.23.0.21.2.5.Final
@@ -111,7 +111,7 @@
4.02.14.0
- 3.0
+ 3.13.03.03.0
@@ -132,12 +132,10 @@
19.3.0.03.14.91.17.5
- 1.22.01.22.0-alpha1.22.0-alpha1.22.0-alpha1.22.0
- 1.22.0-alpha0.33.00.2.10.1.8
@@ -146,7 +144,7 @@
42.4.30.9.02.0.0
- 2.1.16
+ 3.3.42.01.4.22.0.4
@@ -259,26 +257,11 @@
opentelemetry-instrumentation-annotations${version.lib.opentelemetry}
-
- io.opentelemetry
- opentelemetry-context
- ${version.lib.opentelemetry}
-
-
- io.opentelemetry
- opentelemetry-exporter-otlp
- ${version.lib.opentelemetry}
- io.opentelemetry.instrumentationopentelemetry-instrumentation-api${version.lib.opentelemetry}
-
- io.opentelemetry
- opentelemetry-sdk
- ${version.lib.opentelemetry}
- io.opentelemetryopentelemetry-sdk-extension-autoconfigure
@@ -776,7 +759,7 @@
${version.lib.microprofile-lra-api}
- org.jboss
+ io.smallryejandex${version.lib.jandex}
diff --git a/docs/config/config_reference.adoc b/docs/config/config_reference.adoc
index ec42a0dfc42..50d9e921d16 100644
--- a/docs/config/config_reference.adoc
+++ b/docs/config/config_reference.adoc
@@ -45,8 +45,8 @@ The following section lists all configurable types in Helidon.
- xref:{rootdir}/config/io_helidon_security_providers_httpauth_HttpBasicAuthProvider.adoc[HttpBasicAuthProvider (security.providers.httpauth)]
- xref:{rootdir}/config/io_helidon_security_providers_httpauth_HttpDigestAuthProvider.adoc[HttpDigestAuthProvider (security.providers.httpauth)]
- xref:{rootdir}/config/io_helidon_security_providers_httpsign_HttpSignProvider.adoc[HttpSignProvider (security.providers.httpsign)]
-- xref:{rootdir}/config/io_helidon_security_providers_idcs_mapper_IdcsMtRoleMapperRxProvider.adoc[IdcsMtRoleMapperRxProvider (security.providers.idcs.mapper)]
-- xref:{rootdir}/config/io_helidon_security_providers_idcs_mapper_IdcsRoleMapperRxProvider.adoc[IdcsRoleMapperRxProvider (security.providers.idcs.mapper)]
+- xref:{rootdir}/config/io_helidon_security_providers_idcs_mapper_IdcsMtRoleMapperProvider.adoc[IdcsMtRoleMapperRxProvider (security.providers.idcs.mapper)]
+- xref:{rootdir}/config/io_helidon_security_providers_idcs_mapper_IdcsRoleMapperProvider.adoc[IdcsRoleMapperRxProvider (security.providers.idcs.mapper)]
- xref:{rootdir}/config/io_helidon_security_providers_httpsign_InboundClientDefinition.adoc[InboundClientDefinition (security.providers.httpsign)]
- xref:{rootdir}/config/io_helidon_tracing_jaeger_JaegerTracerBuilder.adoc[JaegerTracer (tracing.jaeger)]
- xref:{rootdir}/config/io_helidon_reactive_faulttolerance_Retry_JitterRetryPolicy.adoc[JitterRetryPolicy (faulttolerance.Retry)]
@@ -56,15 +56,14 @@ The following section lists all configurable types in Helidon.
- xref:{rootdir}/config/io_helidon_common_pki_KeyConfig_KeystoreBuilder.adoc[KeystoreBuilder (common.pki.KeyConfig)]
- xref:{rootdir}/config/io_helidon_common_configurable_LruCache.adoc[LruCache (common.configurable)]
- xref:{rootdir}/config/io_helidon_reactive_media_common_MediaContext.adoc[MediaContext (media.common)]
-- xref:{rootdir}/config/io_helidon_microprofile_openapi_MPOpenAPISupport.adoc[MPOpenAPISupport (microprofile.openapi)]
- xref:{rootdir}/config/io_helidon_metrics_api_MetricsSettings.adoc[MetricsSettings (metrics.api)]
- xref:{rootdir}/config/io_helidon_metrics_serviceapi_MetricsSupport.adoc[MetricsSupport (metrics.serviceapi)]
- xref:{rootdir}/config/io_helidon_integrations_micrometer_MicrometerSupport.adoc[MicrometerSupport (integrations.micrometer)]
- xref:{rootdir}/config/io_helidon_config_mp_MpConfigBuilder.adoc[MpConfigBuilder (config.mp)]
- xref:{rootdir}/config/io_helidon_security_providers_oidc_common_OidcConfig.adoc[OidcConfig (security.providers.oidc.common)]
- xref:{rootdir}/config/io_helidon_security_providers_oidc_OidcProvider.adoc[OidcProvider (security.providers.oidc)]
-- xref:{rootdir}/config/io_helidon_openapi_OpenAPISupport.adoc[OpenAPISupport (openapi)]
-- xref:{rootdir}/config/io_helidon_openapi_OpenApiUi.adoc[OpenApiUi (openapi)]
+// - xref:{rootdir}/config/io_helidon_openapi_OpenAPISupport.adoc[OpenAPISupport (openapi)]
+// - xref:{rootdir}/config/io_helidon_openapi_OpenApiUi.adoc[OpenApiUi (openapi)]
- xref:{rootdir}/config/io_helidon_security_providers_common_OutboundConfig.adoc[OutboundConfig (security.providers.common)]
- xref:{rootdir}/config/io_helidon_security_providers_common_OutboundTarget.adoc[OutboundTarget (security.providers.common)]
- xref:{rootdir}/config/io_helidon_common_pki_KeyConfig_PemBuilder.adoc[PemBuilder (common.pki.KeyConfig)]
@@ -75,7 +74,6 @@ The following section lists all configurable types in Helidon.
- xref:{rootdir}/config/io_helidon_common_configurable_Resource.adoc[Resource (common.configurable)]
- xref:{rootdir}/config/io_helidon_servicecommon_rest_RestServiceSettings.adoc[RestServiceSettings (servicecommon.rest)]
- xref:{rootdir}/config/io_helidon_reactive_faulttolerance_Retry.adoc[Retry (faulttolerance)]
-- xref:{rootdir}/config/io_helidon_openapi_SEOpenAPISupport.adoc[SEOpenAPISupport (openapi)]
- xref:{rootdir}/config/io_helidon_common_configurable_ScheduledThreadPoolSupplier.adoc[ScheduledThreadPoolSupplier (common.configurable)]
- xref:{rootdir}/config/io_helidon_security_Security.adoc[Security (security)]
- xref:{rootdir}/config/io_helidon_security_SecurityTime.adoc[SecurityTime (security)]
diff --git a/docs/config/io_helidon_microprofile_openapi_MPOpenAPISupport.adoc b/docs/config/io_helidon_microprofile_openapi_MPOpenAPISupport.adoc
deleted file mode 100644
index 0fa3c2e3c94..00000000000
--- a/docs/config/io_helidon_microprofile_openapi_MPOpenAPISupport.adoc
+++ /dev/null
@@ -1,70 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-
- 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.
-
-///////////////////////////////////////////////////////////////////////////////
-
-ifndef::rootdir[:rootdir: {docdir}/..]
-:description: Configuration of io.helidon.microprofile.openapi.MPOpenAPISupport
-:keywords: helidon, config, io.helidon.microprofile.openapi.MPOpenAPISupport
-:basic-table-intro: The table below lists the configuration keys that configure io.helidon.microprofile.openapi.MPOpenAPISupport
-include::{rootdir}/includes/attributes.adoc[]
-
-= MPOpenAPISupport (microprofile.openapi) Configuration
-
-// tag::config[]
-
-
-Type: link:{javadoc-base-url}/io.helidon.microprofile.openapi/io/helidon/microprofile/openapi/MPOpenAPISupport.html[io.helidon.microprofile.openapi.MPOpenAPISupport]
-
-
-[source,text]
-.Config key
-----
-mp.openapi
-----
-
-
-
-== Configuration options
-
-
-
-.Optional configuration options
-[cols="3,3a,2,5a"]
-
-|===
-|key |type |default value |description
-
-|`application-path-disable` |boolean |`false` |Sets whether the app path search should be disabled.
-|`cors` |xref:{rootdir}/config/io_helidon_reactive_webserver_cors_CrossOriginConfig.adoc[CrossOriginConfig] |{nbsp} |Assigns the CORS settings for the OpenAPI endpoint.
-|`custom-schema-registry-class` |string |{nbsp} |Sets the custom schema registry class.
-|`filter` |string |{nbsp} |Sets the developer-provided OpenAPI filter class name.
-|`model.reader` |string |{nbsp} |Sets the developer-provided OpenAPI model reader class name.
-|`scan.classes` |string[] |{nbsp} |Specify the list of classes to scan.
-|`scan.disable` |boolean |`false` |Disable annotation scanning.
-|`scan.exclude.classes` |string[] |{nbsp} |Specify the list of classes to exclude from scans.
-|`scan.exclude.packages` |string[] |{nbsp} |Specify the list of packages to exclude from scans.
-|`scan.packages` |string[] |{nbsp} |Specify the list of packages to scan.
-|`schema.*` |string |{nbsp} |Sets the schema for the indicated fully-qualified class name (represented here by '*'); value is the schema in JSON format. Repeat for multiple classes.
-|`servers` |string[] |{nbsp} |Sets servers.
-|`servers.operation.*` |string[] |{nbsp} |Sets alternative servers to service the indicated operation (represented here by '*'). Repeat for multiple operations.
-|`servers.path.*` |string[] |{nbsp} |Sets alternative servers to service all operations at the indicated path (represented here by '*'). Repeat for multiple paths.
-|`static-file` |string |`META-INF/openapi.*` |Sets the file system path of the static OpenAPI document file. Default types are `json`, `yaml`, and `yml`.
-|`web-context` |string |`/openapi` |Sets the web context path for the OpenAPI endpoint.
-
-|===
-
-// end::config[]
\ No newline at end of file
diff --git a/docs/config/io_helidon_security_Security.adoc b/docs/config/io_helidon_security_Security.adoc
index a2fac16a86b..502160ed8bc 100644
--- a/docs/config/io_helidon_security_Security.adoc
+++ b/docs/config/io_helidon_security_Security.adoc
@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
- Copyright (c) 2022 Oracle and/or its affiliates.
+ Copyright (c) 2022, 2023 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.
@@ -51,10 +51,10 @@ Such as:
- xref:{rootdir}/config/io_helidon_security_providers_google_login_GoogleTokenProvider.adoc[google-login (GoogleTokenProvider)]
- xref:{rootdir}/config/io_helidon_security_providers_oidc_OidcProvider.adoc[oidc (OidcProvider)]
- xref:{rootdir}/config/io_helidon_security_providers_httpauth_HttpDigestAuthProvider.adoc[http-digest-auth (HttpDigestAuthProvider)]
- - xref:{rootdir}/config/io_helidon_security_providers_idcs_mapper_IdcsMtRoleMapperRxProvider.adoc[idcs-role-mapper (IdcsMtRoleMapperRxProvider)]
+ - xref:{rootdir}/config/io_helidon_security_providers_idcs_mapper_IdcsMtRoleMapperProvider.adoc[idcs-role-mapper (IdcsMtRoleMapperRxProvider)]
- xref:{rootdir}/config/io_helidon_security_providers_jwt_JwtProvider.adoc[jwt (JwtProvider)]
- xref:{rootdir}/config/io_helidon_security_providers_header_HeaderAtnProvider.adoc[header-atn (HeaderAtnProvider)]
- - xref:{rootdir}/config/io_helidon_security_providers_idcs_mapper_IdcsRoleMapperRxProvider.adoc[idcs-role-mapper (IdcsRoleMapperRxProvider)]
+ - xref:{rootdir}/config/io_helidon_security_providers_idcs_mapper_IdcsRoleMapperProvider.adoc[idcs-role-mapper (IdcsRoleMapperRxProvider)]
- xref:{rootdir}/config/io_helidon_security_providers_abac_AbacProvider.adoc[abac (AbacProvider)]
|{nbsp} |Add a provider, works as #addProvider(io.helidon.security.spi.SecurityProvider, String), where the name is set
diff --git a/docs/config/io_helidon_security_providers_idcs_mapper_IdcsMtRoleMapperRxProvider.adoc b/docs/config/io_helidon_security_providers_idcs_mapper_IdcsMtRoleMapperProvider.adoc
similarity index 95%
rename from docs/config/io_helidon_security_providers_idcs_mapper_IdcsMtRoleMapperRxProvider.adoc
rename to docs/config/io_helidon_security_providers_idcs_mapper_IdcsMtRoleMapperProvider.adoc
index d7f976dd689..aaaae6f9990 100644
--- a/docs/config/io_helidon_security_providers_idcs_mapper_IdcsMtRoleMapperRxProvider.adoc
+++ b/docs/config/io_helidon_security_providers_idcs_mapper_IdcsMtRoleMapperProvider.adoc
@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
- Copyright (c) 2022 Oracle and/or its affiliates.
+ Copyright (c) 2022, 2023 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.
@@ -17,9 +17,9 @@
///////////////////////////////////////////////////////////////////////////////
ifndef::rootdir[:rootdir: {docdir}/..]
-:description: Configuration of io.helidon.security.providers.idcs.mapper.IdcsMtRoleMapperRxProvider
-:keywords: helidon, config, io.helidon.security.providers.idcs.mapper.IdcsMtRoleMapperRxProvider
-:basic-table-intro: The table below lists the configuration keys that configure io.helidon.security.providers.idcs.mapper.IdcsMtRoleMapperRxProvider
+:description: Configuration of io.helidon.security.providers.idcs.mapper.IdcsMtRoleMapperProvider
+:keywords: helidon, config, io.helidon.security.providers.idcs.mapper.IdcsMtRoleMapperProvider
+:basic-table-intro: The table below lists the configuration keys that configure io.helidon.security.providers.idcs.mapper.IdcsMtRoleMapperProvider
include::{rootdir}/includes/attributes.adoc[]
= IdcsMtRoleMapperRxProvider (security.providers.idcs.mapper) Configuration
@@ -29,7 +29,7 @@ include::{rootdir}/includes/attributes.adoc[]
Multitenant IDCS role mapping provider
-Type: link:{javadoc-base-url}/io.helidon.security.providers.idcs.mapper/io/helidon/security/providers/idcs/mapper/IdcsMtRoleMapperRxProvider.html[io.helidon.security.providers.idcs.mapper.IdcsMtRoleMapperRxProvider]
+Type: link:{javadoc-base-url}/io.helidon.security.providers.idcs.mapper/io/helidon/security/providers/idcs/mapper/IdcsMtRoleMapperRxProvider.html[io.helidon.security.providers.idcs.mapper.IdcsMtRoleMapperProvider]
[source,text]
diff --git a/docs/config/io_helidon_security_providers_idcs_mapper_IdcsRoleMapperRxProvider.adoc b/docs/config/io_helidon_security_providers_idcs_mapper_IdcsRoleMapperProvider.adoc
similarity index 94%
rename from docs/config/io_helidon_security_providers_idcs_mapper_IdcsRoleMapperRxProvider.adoc
rename to docs/config/io_helidon_security_providers_idcs_mapper_IdcsRoleMapperProvider.adoc
index 6c5268f936e..bb2fa41a179 100644
--- a/docs/config/io_helidon_security_providers_idcs_mapper_IdcsRoleMapperRxProvider.adoc
+++ b/docs/config/io_helidon_security_providers_idcs_mapper_IdcsRoleMapperProvider.adoc
@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
- Copyright (c) 2022 Oracle and/or its affiliates.
+ Copyright (c) 2022, 2023 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.
@@ -17,9 +17,9 @@
///////////////////////////////////////////////////////////////////////////////
ifndef::rootdir[:rootdir: {docdir}/..]
-:description: Configuration of io.helidon.security.providers.idcs.mapper.IdcsRoleMapperRxProvider
-:keywords: helidon, config, io.helidon.security.providers.idcs.mapper.IdcsRoleMapperRxProvider
-:basic-table-intro: The table below lists the configuration keys that configure io.helidon.security.providers.idcs.mapper.IdcsRoleMapperRxProvider
+:description: Configuration of io.helidon.security.providers.idcs.mapper.IdcsRoleMapperProvider
+:keywords: helidon, config, io.helidon.security.providers.idcs.mapper.IdcsRoleMapperProvider
+:basic-table-intro: The table below lists the configuration keys that configure io.helidon.security.providers.idcs.mapper.IdcsRoleMapperProvider
include::{rootdir}/includes/attributes.adoc[]
= IdcsRoleMapperRxProvider (security.providers.idcs.mapper) Configuration
@@ -29,7 +29,7 @@ include::{rootdir}/includes/attributes.adoc[]
IDCS role mapping provider
-Type: link:{javadoc-base-url}/io.helidon.security.providers.idcs.mapper/io/helidon/security/providers/idcs/mapper/IdcsRoleMapperRxProvider.html[io.helidon.security.providers.idcs.mapper.IdcsRoleMapperRxProvider]
+Type: link:{javadoc-base-url}/io.helidon.security.providers.idcs.mapper/io/helidon/security/providers/idcs/mapper/IdcsRoleMapperRxProvider.html[io.helidon.security.providers.idcs.mapper.IdcsRoleMapperProvider]
[source,text]
diff --git a/docs/images/telemetry/telemetry-custom-jaeger.png b/docs/images/telemetry/telemetry-custom-jaeger.png
new file mode 100644
index 00000000000..0fca937ce92
Binary files /dev/null and b/docs/images/telemetry/telemetry-custom-jaeger.png differ
diff --git a/docs/images/telemetry/telemetry-general.png b/docs/images/telemetry/telemetry-general.png
new file mode 100644
index 00000000000..eb7b81d1e95
Binary files /dev/null and b/docs/images/telemetry/telemetry-general.png differ
diff --git a/docs/images/telemetry/telemetry-greeting-jaeger.png b/docs/images/telemetry/telemetry-greeting-jaeger.png
new file mode 100644
index 00000000000..42c6d4fb2f2
Binary files /dev/null and b/docs/images/telemetry/telemetry-greeting-jaeger.png differ
diff --git a/docs/images/telemetry/telemetry-outbound-jaeger.png b/docs/images/telemetry/telemetry-outbound-jaeger.png
new file mode 100644
index 00000000000..55785161c93
Binary files /dev/null and b/docs/images/telemetry/telemetry-outbound-jaeger.png differ
diff --git a/docs/includes/attributes.adoc b/docs/includes/attributes.adoc
index 1684198e8dd..2b801136cf5 100644
--- a/docs/includes/attributes.adoc
+++ b/docs/includes/attributes.adoc
@@ -75,7 +75,7 @@ endif::[]
:version-lib-oracle-jdbc: 21
:version-lib-oracle-ucp: {version-lib-oracle-jdbc}
:version-plugin-jib: 0.10.1
-:version-plugin-jandex: 1.0.6
+:version-plugin-jandex: 3.1.2
:version-lib-micrometer: 1.6.6
:version-lib-smallrye-open-api: 2.1.16
@@ -93,7 +93,7 @@ endif::[]
:microprofile-open-api-base-url: {microprofile-base-url}/microprofile-open-api-{version-lib-microprofile-openapi-api}
:microprofile-open-api-spec-url: {microprofile-open-api-base-url}/microprofile-openapi-spec-{version-lib-microprofile-openapi-api}.html
:microprofile-open-api-javadoc-base-url: {microprofile-open-api-base-url}/apidocs
-:microprofile-open-api-javadoc-url: {microprofile-open-api-javadoc-base-url}/apidocs/org/eclipse/microprofile/openapi/
+:microprofile-open-api-javadoc-url: {microprofile-open-api-javadoc-base-url}/org/eclipse/microprofile/openapi
:microprofile-lra-base-url: {microprofile-base-url}/microprofile-lra-{version-lib-microprofile-lra-api}
:microprofile-lra-spec-url: {microprofile-lra-base-url}/microprofile-lra-spec-{version-lib-microprofile-lra-api}.html
diff --git a/docs/includes/openapi.adoc b/docs/includes/openapi.adoc
deleted file mode 100644
index e0a7952378f..00000000000
--- a/docs/includes/openapi.adoc
+++ /dev/null
@@ -1,210 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-
- 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.
-
-///////////////////////////////////////////////////////////////////////////////
-
-ifndef::rootdir[:rootdir: {docdir}/..]
-
-// tag::overview[]
-The link:{openapi-spec-url}[OpenAPI specification] defines a standard way to express the interface exposed by a REST service.
-
-The link:{microprofile-open-api-spec-url}[MicroProfile OpenAPI spec] explains how MicroProfile embraces OpenAPI, adding annotations, configuration, and a service provider interface (SPI).
-
-ifdef::mp-flavor[Helidon {flavor-uc} implements the MicroProfile OpenAPI specification.]
-ifdef::se-flavor[OpenAPI support in Helidon {flavor-uc} draws its inspiration from MicroProfile OpenAPI but does not implement the spec because Helidon {flavor-uc} does not support annotations.]
-
-The OpenAPI support in Helidon {flavor-uc} performs two main tasks:
-
-* Build an in-memory model of the REST API your service implements.
-* Expose the model in text format (typically YAML) via the `/openapi` endpoint.
-
-To construct the model, Helidon gathers information about the service API from whichever of these sources are present in the application:
-
-* a _model reader_
-+
-The SPI defines an interface you can implement in your application for programmatically providing part or all of the model;
-* a static OpenAPI document file packaged as part of your service;
-ifdef::mp-flavor[]
-* OpenAPI annotations;
-endif::[]
-* a _filter_ class
-+
-The SPI defines an interface you can implement in your application which can mask parts of the model.
-
-
-// end::overview[]
-
-// tag::furnish-openapi-info[]
-
-==== Furnish OpenAPI information about your endpoints
-// It's a bit odd to intermix the SE and MP content in this common file this way.
-// But I tried having a level 3 section in the SE file include a sequence of
-// level 4 sections from here, and that led to errors with headers being out of sequence.
-// With the entire level 3 section here and conditional text for SE and MP, AsciiDoctor is happy.
-ifdef::se-flavor[]
-OpenAPI support in Helidon SE largely follows the link:{microprofile-open-api-spec-url}[MicroProfile OpenAPI spec].
-But because Helidon SE does not process annotations, your application supplies data for the OpenAPI model in the other ways listed earlier.
-endif::[]
-
-ifdef::mp-flavor[]
-Helidon MP OpenAPI combines information from all of the following sources as it
-builds its in-memory model of your application's API. It constructs the OpenAPI
-document from this internal model. Your application can use one or more of these
-techniques.
-
-===== Annotate the endpoints in your app
-You can add MicroProfile OpenAPI annotations to the endpoints in your source code.
-These annotations allow the Helidon MP OpenAPI runtime to discover the endpoints
-and information about them via CDI at app start-up.
-
-Here is one of the endpoints, annotated for OpenAPI, from the example mentioned earlier:
-
-[source,java]
-----
-@GET
-@Operation(summary = "Returns a generic greeting", // <1>
- description = "Greets the user generically")
-@APIResponse(description = "Simple JSON containing the greeting", // <2>
- content = @Content(mediaType = "application/json",
- schema = @Schema(implementation = GreetingMessage.class)))
-@Produces(MediaType.APPLICATION_JSON)
-public JsonObject getDefaultMessage() {...}
-----
-<1> `@Operation` gives information about this endpoint.
-<2> `@APIResponse` describes the HTTP response and declares its media type and contents.
-
-You can also define any request parameters the endpoint expects, although this
-endpoint uses none.
-
-This excerpt shows only a few annotations for illustration. The
-link:{helidon-github-tree-url}/examples/microprofile/openapi-basic[Helidon MP OpenAPI example] illustrates more,
-and the link:{microprofile-open-api-spec-url}[MicroProfile OpenAPI spec] describes them all.
-
-===== Provide a static OpenAPI file
-Add a static file at `META-INF/openapi.yml`, `META-INF/openapi.yaml`,
-or `META-INF/openapi.json`. Tools such as Swagger let you describe your app's API
-and they then generate an OpenAPI document file which you can include in your application
-so OpenAPI can use it.
-
-===== Write and configure a model reader class
-Write a Java class that implements the OpenAPI
-link:{microprofile-open-api-javadoc-url}/OASModelReader.html[`org.eclipse.microprofile.openapi.OASModelReader`] interface. Your
-model reader code programmatically adds elements to the internal model that OpenAPI
-builds.
-
-endif::[]
-
-===== Provide a static OpenAPI file
-Add a static file at `META-INF/openapi.yml`, `META-INF/openapi.yaml`,
-or `META-INF/openapi.json`. Tools such as Swagger let you describe your app's API
-and they then generate an OpenAPI document file which you can include in your application
-so OpenAPI can use it.
-
-===== Write and configure a model reader class
-Write a Java class that implements the OpenAPI
-link:{microprofile-open-api-javadoc-url}/OASModelReader.html[`org.eclipse.microprofile.openapi.OASModelReader`] interface. Your
-model reader code programmatically adds elements to the internal model that OpenAPI
-builds.
-
-Change your application's MP configuration to set `mp.openapi.model.reader` as the
-fully-qualified class name of your class.
-
-===== Write and configure a filter class
-Write a Java class that implements the OpenAPI
-link:{microprofile-open-api-javadoc-url}/OASFilter.html[`org.eclipse.microprofile.openapi.OASFilter`] interface.
-As OpenAPI composes its internal model, it invokes your filter with each
-model element _before_ adding the element to the model. Your filter can
-accept the element as-is, modify it, or suppress it.
-
-Change your application's configuration to set `mp.openapi.filter` as the full-qualified
-class name of your class.
-
-// end::furnish-openapi-info[]
-
-// tag::usage-access-endpoint[]
-=== Accessing the REST Endpoint
-Once you add the {flavor-uc} OpenAPI dependency to your
-ifdef::mp-flavor[project,]
-ifdef::se-flavor[project and add code to create the `OpenAPISupport` object to your routing,]
-your application will automatically respond to the built-in endpoint --
-`/openapi` -- and it will return the OpenAPI document describing the endpoints
-in your application.
-
-By default, per the MicroProfile OpenAPI spec, the default format of the OpenAPI document is YAML.
-There is not yet an adopted IANA YAML media type, but a proposed one specifically
-for OpenAPI documents that has some support is `application/vnd.oai.openapi`.
-That is what Helidon returns, by default.
-
-In addition, a client can specify the HTTP header `Accept` as either `application/vnd.oai.openapi+json` or
-`application/json` to request JSON. Alternatively, the client can pass the query parameter `format` as either `JSON`
-or `YAML` to receive `application/json` or `application/vnd.oai.openapi` (YAML) output, respectively.
-// end::usage-access-endpoint[]
-
-// tag::api[]
-ifdef::mp-flavor[]
-The link:{microprofile-open-api-spec-url}[MicroProfile OpenAPI specification] gives a listing and brief examples of the annotations you can add to your code to convey OpenAPI information.
-endif::[]
-
-The link:{microprofile-open-api-javadoc-base-url}[MicroProfile OpenAPI JavaDocs] give full details of the
-ifdef::mp-flavor[annotations and the other]
-classes and interfaces you can use in your code.
-ifdef::se-flavor[]
-Remember that, although the JavaDocs describe annotations, Helidon {flavor-uc} does not support them.
-endif::[]
-
-// end::api[]
-
-
-// tag::additional-building-jandex[]
-
-=== Building the Jandex index
-
-A Jandex index stores information about the classes and methods in your app and
-what annotations they have. It allows CDI to process annotations faster during your
-application's start-up.
-
-Add the link:https://github.com/wildfly/jandex-maven-plugin[Jandex maven plug-in] to the ``
-section of your `pom.xml`:
-
-[source,xml,subs="attributes+"]
-----
-
- org.jboss.jandex
- jandex-maven-plugin
- {jandex-plugin-version}
-
-
- make-index
-
- jandex
-
-
-
-
-----
-When you build your app `maven` should include the index `META-INF/jandex.idx` in
-the JAR.
-
-[NOTE]
-====
-If you _do not_ modify your build to create
-the index then the Helidon MP OpenAPI runtime automatically creates one in memory during
-app start-up. This slows down your app start-up and, depending on how CDI is
-configured, might inadvertently miss information.
-
-We _strongly recommend_ using the Jandex plug-in to build the index into your app.
-====
-// end::additional-building-jandex[]
\ No newline at end of file
diff --git a/docs/includes/openapi/openapi.adoc b/docs/includes/openapi/openapi.adoc
index 3d704d476bd..ea3e628d03f 100644
--- a/docs/includes/openapi/openapi.adoc
+++ b/docs/includes/openapi/openapi.adoc
@@ -185,13 +185,13 @@ A Jandex index stores information about the classes and methods in your app and
what annotations they have. It allows CDI to process annotations faster during your
application's start-up.
-Add the link:https://github.com/wildfly/jandex-maven-plugin[Jandex maven plug-in] to the ``
+Add the link:https://github.com/smallrye/jandex/maven-plugin[Jandex maven plug-in] to the ``
section of your `pom.xml`:
[source,xml,subs="attributes+"]
----
- org.jboss.jandex
+ io.smallryejandex-maven-plugin{jandex-plugin-version}
diff --git a/docs/includes/security/providers/idcs-role-mapper.adoc b/docs/includes/security/providers/idcs-role-mapper.adoc
index 463689e6d4e..6785a93866f 100644
--- a/docs/includes/security/providers/idcs-role-mapper.adoc
+++ b/docs/includes/security/providers/idcs-role-mapper.adoc
@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
- Copyright (c) 2020, 2022 Oracle and/or its affiliates.
+ Copyright (c) 2020, 2023 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.
@@ -38,11 +38,11 @@ A role mapper to retrieve roles from Oracle IDCS.
==== Single-tenant IDCS Role Mapper
-include::{rootdir}/config/io_helidon_security_providers_idcs_mapper_IdcsRoleMapperRxProvider.adoc[leveloffset=+2,tag=config]
+include::{rootdir}/config/io_helidon_security_providers_idcs_mapper_IdcsRoleMapperProvider.adoc[leveloffset=+2,tag=config]
==== Multi-tenant IDCS Role Mapper
-include::{rootdir}/config/io_helidon_security_providers_idcs_mapper_IdcsMtRoleMapperRxProvider.adoc[leveloffset=+2,tag=config]
+include::{rootdir}/config/io_helidon_security_providers_idcs_mapper_IdcsMtRoleMapperProvider.adoc[leveloffset=+2,tag=config]
==== Example code
diff --git a/docs/mp/graphql.adoc b/docs/mp/graphql.adoc
index 45a8ecd04a5..4c97223a0d4 100644
--- a/docs/mp/graphql.adoc
+++ b/docs/mp/graphql.adoc
@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
- Copyright (c) 2019, 2022 Oracle and/or its affiliates.
+ Copyright (c) 2019, 2023 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.
@@ -147,7 +147,7 @@ using the `jandex-maven-plugin` for all API and POJO classes.
.Generate Jandex index
----
- org.jboss.jandex
+ io.smallryejandex-maven-plugin
diff --git a/docs/mp/guides/mp-tutorial.adoc b/docs/mp/guides/mp-tutorial.adoc
index 62abc0557ca..1d7b2fbf28d 100644
--- a/docs/mp/guides/mp-tutorial.adoc
+++ b/docs/mp/guides/mp-tutorial.adoc
@@ -84,7 +84,7 @@ Create a new Maven POM file (called `pom.xml`) and add the following
- org.jboss.jandex
+ io.smallryejandex-maven-plugin
diff --git a/docs/mp/introduction/microprofile.adoc b/docs/mp/introduction/microprofile.adoc
index fabd23e2c88..cca194b1f8d 100644
--- a/docs/mp/introduction/microprofile.adoc
+++ b/docs/mp/introduction/microprofile.adoc
@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
- Copyright (c) 2019, 2020 Oracle and/or its affiliates.
+ Copyright (c) 2019, 2023 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.
@@ -132,9 +132,9 @@ To use Jandex, configure a Maven plugin that adds the index to your
.jandex dependency
----
- org.jboss
+ io.smallryejandex
- 2.0.4.Final
+ {version.plugin.jandex}
----
@@ -144,9 +144,9 @@ To use Jandex, configure a Maven plugin that adds the index to your
- org.jboss.jandex
+ io.smallryejandex-maven-plugin
- 1.0.5
+ 3.1.2make-index
diff --git a/docs/mp/openapi.adoc b/docs/mp/openapi.adoc
deleted file mode 100644
index 2707736fcf5..00000000000
--- a/docs/mp/openapi.adoc
+++ /dev/null
@@ -1,272 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-
- Copyright (c) 2019, 2023 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.
-
-///////////////////////////////////////////////////////////////////////////////
-
-= OpenAPI
-:toc:
-:toc-placement: preamble
-:description: Helidon MP OpenAPI Support
-:keywords: helidon, mp, microprofile, openapi
-:feature-name: MicroProfile OpenAPI
-:microprofile-bundle: true
-:rootdir: {docdir}/..
-
-include::{rootdir}/includes/mp.adoc[]
-
-== Contents
-
-- <>
-- <>
-- <>
-- <>
-- <>
-- <>
-- <>
-
-== Overview
-
-include::{rootdir}/includes/openapi.adoc[tag=overview]
-
-include::{rootdir}/includes/dependencies.adoc[]
-
-[source,xml,subs="attributes+"]
-----
-
-
- org.eclipse.microprofile.openapi
- microprofile-openapi-api
-
-
- io.helidon.microprofile.openapi
- helidon-microprofile-openapi
- runtime
-
-
-----
-<1> Defines the MicroProfile OpenAPI annotations so you can use them in your code.
-<2> Adds the Helidon MP OpenAPI runtime support.
-
-== Usage
-
-=== OpenAPI support in Helidon MP
-
-You can very simply add support for OpenAPI to your Helidon MP application. This
-document shows what changes you need to make to your application and how to access
-the OpenAPI document for your application at runtime.
-
-=== Changing your application
-
-To use OpenAPI from your Helidon MP app, in addition to adding dependencies as described above:
-
-1. Furnish OpenAPI information about your application's endpoints.
-2. Update your application's configuration (optional).
-
-include::{rootdir}/includes/openapi.adoc[tag=furnish-openapi-info]
-
-=== Update your application configuration
-Beyond the two config properties that denote the model reader and filter, Helidon
-MP OpenAPI supports a number of other mandated settings. These are described in the
-link:{microprofile-open-api-spec-url}#configuration[configuration section] of the MicroProfile
-OpenAPI spec.
-
-include::{rootdir}/includes/openapi.adoc[tag=usage-access-endpoint]
-
-== API
-
-include::{rootdir}/includes/openapi.adoc[tag=api]
-
-== Configuration
-
-Helidon OpenAPI configuration supports the following settings:
-
-include::{rootdir}/config/io_helidon_microprofile_openapi_MPOpenAPISupport.adoc[leveloffset=+1,tag=config]
-
-== Examples
-
-Helidon MP includes a link:{helidon-github-tree-url}/examples/microprofile/openapi-basic[complete OpenAPI example]
-based on the MP quick-start sample app. The rest of this section shows, step-by-step, how one might change the original QuickStart service to adopt OpenAPI.
-
-=== Helidon MP Basic OpenAPI Example
-
-This example shows a simple greeting application, similar to the one from the
-Helidon MP QuickStart, enhanced with OpenAPI support.
-
-[source,java]
-----
-@Path("/greeting")
-@PUT
-@Operation(summary = "Set the greeting prefix",
- description = "Permits the client to set the prefix part of the greeting (\"Hello\")") //<1>
-@RequestBody( //<2>
- name = "greeting",
- description = "Conveys the new greeting prefix to use in building greetings",
- content = @Content(
- mediaType = "application/json",
- schema = @Schema(implementation = GreetingUpdateMessage.class),
- examples = @ExampleObject(
- name = "greeting",
- summary = "Example greeting message to update",
- value = "{\"greeting\": \"New greeting message\"}")))
-@Consumes(MediaType.APPLICATION_JSON)
-@Produces(MediaType.APPLICATION_JSON)
-public Response updateGreeting(JsonObject jsonObject) {
- ...
-}
-----
-<1> With `@Operation` annotation we document the current method.
-<2> With `@RequestBody` annotation we document the content produced. Internal annotations `@Content`, `@Schema` and
- `@ExampleObjects` are used to give more details about the returned data.
-
-If we want to hide a specific path an `OASFilter` is used.
-
-The OASFilter interface allows application developers to receive callbacks for various key OpenAPI elements. The
- interface has a default implementation for every method, which allows application developers to only override the
- methods they care about. To use it, simply create an implementation of this interface and register it using the
- `mp.openapi.filter configuration` key, where the value is the fully qualified name of the filter class.
-
-The following example filter prevents information about a given path from appearing in the OpenAPI document.
-
-[source, java]
-----
-import org.eclipse.microprofile.openapi.models.Operation;
-import org.eclipse.microprofile.openapi.models.PathItem;
-
-public class SimpleAPIFilter implements OASFilter {
-
- @Override
- public PathItem filterPathItem(PathItem pathItem) {
- for (Map.Entry methodOp
- : pathItem.getOperations().entrySet()) {
- if (SimpleAPIModelReader.DOOMED_OPERATION_ID
- .equals(methodOp.getValue().getOperationId())) {
- return null;
- }
- }
- return OASFilter.super.filterPathItem(pathItem);
- }
-}
-----
-
-You can implement a model reader to provide all or part of the in-memory `OpenAPI` model programmatically. Helidon
- `OpenAPI` merges the model from the model reader with models from the other sources (a static file and annotations).
-
-The example model reader below creates an `OpenAPI` object describing two paths. It turns out that the filter described
-earlier will suppress one of the paths, but the model reader does not know or care.
-
-[source,java]
-----
-import org.eclipse.microprofile.openapi.OASFactory;
-import org.eclipse.microprofile.openapi.OASModelReader;
-import org.eclipse.microprofile.openapi.models.OpenAPI;
-import org.eclipse.microprofile.openapi.models.PathItem;
-import org.eclipse.microprofile.openapi.models.Paths;
-
-/**
- * Defines two paths using the OpenAPI model reader mechanism, one that should
- * be suppressed by the filter class and one that should appear in the published
- * OpenAPI document.
- */
-public class SimpleAPIModelReader implements OASModelReader {
-
- /**
- * Path for the example endpoint added by this model reader that should be visible.
- */
- public static final String MODEL_READER_PATH = "/test/newpath";
-
- /**
- * Path for an endpoint that the filter should hide.
- */
- public static final String DOOMED_PATH = "/test/doomed";
-
- /**
- * ID for an endpoint that the filter should hide.
- */
- public static final String DOOMED_OPERATION_ID = "doomedPath";
-
- /**
- * Summary text for the endpoint.
- */
- public static final String SUMMARY = "A sample test endpoint from ModelReader";
-
- @Override
- public OpenAPI buildModel() {
- /*
- * Add two path items, one of which we expect to be removed by
- * the filter and a very simple one that will appear in the
- * published OpenAPI document.
- */
- PathItem newPathItem = OASFactory.createPathItem()
- .GET(OASFactory.createOperation()
- .operationId("newPath")
- .summary(SUMMARY));
- PathItem doomedPathItem = OASFactory.createPathItem()
- .GET(OASFactory.createOperation()
- .operationId(DOOMED_OPERATION_ID)
- .summary("This should become invisible"));
- OpenAPI openAPI = OASFactory.createOpenAPI();
- Paths paths = OASFactory.createPaths()
- .addPathItem(MODEL_READER_PATH, newPathItem)
- .addPathItem(DOOMED_PATH, doomedPathItem);
- openAPI.paths(paths);
-
- return openAPI;
- }
-}
-----
-
-Having written the filter and model reader classes, identify them by adding configuration to
- `META-INF/microprofile-config.properties` as the following example shows.
-
-[source,properties]
-----
-mp.openapi.filter=io.helidon.microprofile.examples.openapi.basic.internal.SimpleAPIFilter
-mp.openapi.model.reader=io.helidon.microprofile.examples.openapi.basic.internal.SimpleAPIModelReader
-----
-
-
-Now just build and run:
-
-[source,bash]
-----
-mvn package
-java -jar target/helidon-examples-microprofile-openapi-basic.jar
-----
-
-Try the endpoints:
-
-[source,bash]
-----
-curl -X GET http://localhost:8080/greet
-{"message":"Hello World!"}
-
-curl -X GET http://localhost:8080/openapi
-[lengthy OpenAPI document]
-----
-
-The output describes not only then endpoints from `GreetResource` but
-also one contributed by the `SimpleAPIModelReader`.
-
-Full example is available link:{helidon-github-tree-url}}/examples/microprofile/openapi-basic[in our official repository]
-
-
-== Additional Information
-include::{rootdir}/includes/openapi.adoc[tag=additional-building-jandex]
-
-== Reference
-
-* link:https://github.com/eclipse/microprofile-open-api[MicroProfile OpenAPI GitHub Repository]
-* link:{microprofile-open-api-spec-url}[MicroProfile OpenAPI Specification]
diff --git a/docs/mp/openapi/openapi.adoc b/docs/mp/openapi/openapi.adoc
index d418130b491..78700f59f86 100644
--- a/docs/mp/openapi/openapi.adoc
+++ b/docs/mp/openapi/openapi.adoc
@@ -85,10 +85,10 @@ include::{incdir}/openapi.adoc[tag=usage-access-endpoint]
include::{incdir}/openapi.adoc[tag=api]
== Configuration
-
-Helidon OpenAPI configuration supports the following settings:
-
-include::{rootdir}/config/io_helidon_microprofile_openapi_MPOpenAPISupport.adoc[leveloffset=+1,tag=config]
+//
+// Helidon OpenAPI configuration supports the following settings:
+//
+//include::{rootdir}/config/io_helidon_microprofile_openapi_MPOpenAPISupport.adoc[leveloffset=+1,tag=config]
== Examples
diff --git a/docs/mp/telemetry.adoc b/docs/mp/telemetry.adoc
new file mode 100644
index 00000000000..f4545834241
--- /dev/null
+++ b/docs/mp/telemetry.adoc
@@ -0,0 +1,408 @@
+///////////////////////////////////////////////////////////////////////////////
+
+ Copyright (c) 2023 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.
+
+///////////////////////////////////////////////////////////////////////////////
+
+= Telemetry
+:description: Helidon MP Telemetry Support
+:feature-name: MicroProfile Telemetry
+:keywords: helidon, telemetry, microprofile, micro-profile
+:microprofile-bundle: true
+:rootdir: {docdir}/..
+
+include::{rootdir}/includes/mp.adoc[]
+
+== Contents
+
+- <>
+- <>
+- <>
+- <>
+- <>
+- <>
+- <>
+
+== Overview
+
+include::{rootdir}/includes/dependencies.adoc[]
+
+[source,xml]
+----
+
+ io.helidon.microprofile.telemetry
+ helidon-microprofile-telemetry
+
+----
+
+== Usage
+
+link:https://opentelemetry.io/[OpenTelemetry] comprises a collection of APIs, SDKs, integration tools, and other software components intended to facilitate the generation and control of telemetry data, including traces, metrics, and logs. In an environment where distributed tracing is enabled via OpenTelemetry (which combines OpenTracing and OpenCensus), this specification establishes the necessary behaviors for MicroProfile applications to participate seamlessly.
+
+MicroProfile Telemetry 1.0 allows for the exportation of the data it collects to Jaeger or Zipkin and to other systems using variety of exporter.
+
+In a distributed tracing system, *traces* are used to capture a series of requests and are composed of multiple *spans* that represent individual operations within those requests. Each *span* includes a name, timestamps, and metadata that provide insights into the corresponding operation.
+
+*Context* is included in each span to identify the specific request that it belongs to. This context information is crucial for tracking requests across various components in a distributed system, enabling developers to trace a single request as it traverses through multiple services.
+
+Finally, *exporters* are responsible for transmitting the collected trace data to a backend service for monitoring and visualization. This enables developers to gain a comprehensive understanding of the system's behavior and detect any issues or bottlenecks that may arise.
+
+image::telemetry/telemetry-general.png[General understanding of OpenTelemetry Tracing]
+
+There are two ways to work with Telemetry, using:
+
+- Automatic Instrumentation
+- Manual Instrumentation
+
+For Automatic Instrumentation, OpenTelemetry provides a JavaAgent. The Tracing API allows for the automatic participation in distributed tracing of Jakarta RESTful Web Services (both server and client) as well as MicroProfile REST Clients, without requiring any modifications to the code. This is achieved through automatic instrumentation.
+
+For Manual Instrumentation there is a set of annotations and access to OpenTelemetry API.
+
+`@WithSpan` - By adding this annotation to a method in any Jakarta CDI aware bean, a new Span will be created and any necessary connections to the current Trace context will be established. Additionally, the `SpanAttribute` annotation can be used to mark method parameters that should be included in the Trace.
+
+Helidon provides full access to OpenTelemetry Tracing API:
+
+* `io.opentelemetry.api.OpenTelemetry`
+* `io.opentelemetry.api.trace.Tracer`
+* `io.opentelemetry.api.trace.Span`
+* `io.opentelemetry.api.baggage.Baggage`
+
+Accessing and using these objects can be done as follows. For span:
+
+.Span sample
+[source, java]
+----
+@ApplicationScoped
+class HelidonBean {
+
+ @WithSpan <1>
+ void doSomethingWithinSpan() {
+ // do something here
+ }
+
+ @WithSpan("name", kind = SpanKind.SERVER, @SpanAttribute(value = "arg") String arg) <2>
+ void complexSpan() {
+ // do something here
+ }
+}
+----
+<1> Simple `@WithSpan` annotation usage.
+<2> Additional attributes can be set to the annotation.
+
+You can also inject OpenTelemetry `Tracer` using the regular `@Inject` annotation and use `SpanBuilder` to manually create, star, and stop Spans.
+
+.SpanBuilder usage
+[source, java]
+----
+@Path("/")
+public class HelidonEndpoint {
+
+ @Inject
+ Tracer tracer; <1>
+
+ @GET
+ @Path("/span")
+ public Response span() {
+ Span span = tracer.spanBuilder("new") <2>
+ .setSpanKind(SpanKind.CLIENT)
+ .setAttribute("someAttribute", "someValue")
+ .startSpan();
+
+ span.end();
+
+ return Response.ok().build();
+ }
+}
+----
+<1> Inject `Tracer`.
+<2> Use `Tracer.spanBuilder` to create and start new `Span`.
+
+To obtain the current span, it can be injected by CDI. The current span can also be obtained using the static method `Span.current()`.
+
+.Inject the current span
+[source, java]
+----
+@Path("/")
+public class HelidonEndpoint {
+ @Inject
+ Span span; <1>
+
+ @GET
+ @Path("/current")
+ public Response currentSpan() {
+ return Response.ok(span.getAttribute("someAttribute")).build(); <2>
+ }
+
+
+ @GET
+ @Path("/current/static")
+ public Response currentSpanStatic() {
+ return Response.ok(Span.current().getAttribute("someAttribute")).build(); <3>
+ }
+}
+----
+<1> Inject the current span.
+<2> Use the injected span.
+<3> Use `Span.current()` to access the current span.
+
+The same functionality is available for the `Baggage` API:
+
+.Inject the current baggage
+[source, java]
+----
+@Path("/")
+public class HelidonEndpoint {
+ @Inject
+ Baggage baggage; <1>
+
+ @GET
+ @Path("/current")
+ public Response currentBaggage() {
+ return Response.ok(baggage.get("baggageKey")).build(); <2>
+ }
+
+
+ @GET
+ @Path("/current/static")
+ public Response currentBaggageStatic() {
+ return Response.ok(Baggage.current().get("baggageKey")).build(); <3>
+ }
+}
+----
+<1> Inject the current baggage.
+<2> Use the injected baggage.
+<3> Use `Baggage.current()` to access the current baggage.
+
+
+== Configuration
+
+IMPORTANT: MicroProfile Telemetry is not activated by default. To activate this feature, you need to specify the configuration `otel.sdk.disabled=false` in one of the MicroProfile Config or other config sources.
+
+To configure OpenTelemetry, MicroProfile Config must be used, and the configuration properties outlined in the following sections must be followed:
+
+- link:https://github.com/open-telemetry/opentelemetry-java/tree/v1.19.0/sdk-extensions/autoconfigure[OpenTelemetry SDK Autoconfigure] (excluding properties related to Metrics and Logging)
+- link:https://opentelemetry.io/docs/instrumentation/java/manual/[Manual Instrumentation]
+
+Please consult with the links above for all configurations properties usage.
+
+The property should be declared in `microprofile-config.properties` file in order to be processed correctly.
+
+
+=== OpenTelemetry Java Agent
+
+The OpenTelemetry Java Agent may influence the work of MicroProfile Telemetry, on how the objects are created and configured. Helidon will do "best effort" detect the use of the agent. But, if there is a decision to run the Helidon app with the agent, a configuration property should be set:
+
+`otel.agent.present=true`
+
+This way, Helidon will explicitly get all the configuration and objects from the Agent, thus allowing correct Span hierarchy settings.
+
+== Examples
+
+This guide demonstrates how to incorporate MicroProfile Telemetry into Helidon and provides illustrations of how to view traces. Jaeger is employed in all the examples, and the Jaeger UI is used to view the traces.
+
+=== Set Up Jaeger
+
+For the examples Jaeger will be used for gathering of the tracing information.
+
+.Run Jaeger in a docker container.
+[source, bash]
+----
+docker run -d --name jaeger \
+ -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
+ -e COLLECTOR_OTLP_ENABLED=true \
+ -p 6831:6831/udp \
+ -p 6832:6832/udp \
+ -p 5778:5778 \
+ -p 16686:16686 \
+ -p 4317:4317 \
+ -p 4318:4318 \
+ -p 14250:14250 \
+ -p 14268:14268 \
+ -p 14269:14269 \
+ -p 9411:9411 \
+ jaegertracing/all-in-one:1.41
+----
+
+All the tracing information gathered from the examples runs is accessible from the browser in the Jaeger UI under link:http://localhost:16686/[]
+
+=== Enable MicroProfile Telemetry in Helidon Application
+
+Together with Helidon Telemetry dependency, an OpenTelemetry Exporter dependency should be added to project's pom.xml file.
+
+[source,xml]
+----
+
+ io.helidon.microprofile.telemetry
+ helidon-microprofile-telemetry <1>
+
+
+ io.opentelemetry
+ opentelemetry-exporter-jaeger <2>
+
+----
+<1> Helidon Telemetry dependency.
+<2> OpenTelemetry Jaeger exporter.
+
+Add these lines to `META-INF/microprofile-config.properties`:
+
+.MicroProfile Telemetry properties
+[source,properties]
+----
+otel.sdk.disabled=false <1>
+otel.traces.exporter=jaeger <2>
+otel.exporter.name=greeting-service <3>
+----
+<1> Enable MicroProfile Telemetry.
+<2> Set exporter to Jaeger.
+<3> Name of our service.
+
+Here we enable MicroProfile Telemetry, set tracer to "jaeger" and give a name, which will be used to identify our service in the tracer.
+
+[NOTE]
+====
+
+For this example, you will use Jaeger to manage data tracing. If you prefer to use Zipkin, please set `otel.traces.exporter` property to "zipkin". For more information using about Zipkin, see link:https://zipkin.io/[]. Also a corresponding Maven dependency for the exporter should be added:
+----
+
+ io.opentelemetry
+ opentelemetry-exporter-zipkin
+
+----
+====
+
+
+=== Tracing at Method Level
+
+To create simple services, use `@WithSpan` and `Tracer` to create span and let MicroProfile OpenTelemetry handle them.
+
+[source, java]
+----
+@Path("/greet")
+public class GreetResource {
+
+ @GET
+ @WithSpan("default") <1>
+ public String getDefaultMessage() {
+ return "Hello World";
+ }
+}
+----
+<1> Use of `@WithSpan` with name "default".
+
+Now let's call the Greeting endpoint:
+
+[source,bash]
+----
+curl localhost:8080/greet
+Hello World
+----
+
+Next, launch the Jaeger UI at link:http://localhost:16686/[]. The expected output is:
+
+image::telemetry/telemetry-greeting-jaeger.png[Greeting service tracing output]
+
+.Custom method
+[source,java]
+----
+@Inject
+private Tracer tracer; <1>
+
+@GET
+@Path("custom")
+@Produces(MediaType.APPLICATION_JSON)
+@WithSpan <2>
+public JsonObject useCustomSpan(){
+ Span span = tracer.spanBuilder("custom") <3>
+ .setSpanKind(SpanKind.INTERNAL)
+ .setAttribute("attribute", "value")
+ .startSpan();
+ span.end(); <4>
+
+ return JSON.createObjectBuilder()
+ .add("Custom Span", span.toString())
+ .build();
+}
+----
+<1> Inject Opentelemetry `Tracer`.
+<2> Create Span around the method `useCustomSpan()`.
+<3> Create a custom `INTERNAL` span and start it.
+<4> End the custom span.
+
+Let us call the custom endpoint:
+
+[source,bash]
+----
+curl localhost:8080/greeting/custom
+----
+
+Again you can launch the Jaeger UI at link:http://localhost:16686/[]. The expected output is:
+
+image::telemetry/telemetry-custom-jaeger.png[Custom span usage]
+
+Now let us use multiple services calls. In the example below our main service will call the `secondary` services. Each method in each service will be annotated with `@WithSpan` annotation.
+
+.Outbound method
+[source,java]
+----
+@Uri("http://localhost:8081/secondary")
+private WebTarget target; <1>
+
+@GET
+@Path("/outbound")
+@WithSpan("outbound") <2>
+public String outbound() {
+ return target.request().accept(MediaType.TEXT_PLAIN).get(String.class); <3>
+}
+----
+<1> Inject `WebTarget` pointing to Secondary service.
+<2> Wrap method using `WithSpan`.
+<3> Call the secondary service.
+
+The secondary service is very simple, it has only one method, which is also annotated with `@WithSpan`.
+
+.Secondary service
+[source, java]
+----
+@GET
+@WithSpan <1>
+public String getSecondaryMessage() {
+ return "Secondary"; <2>
+}
+----
+<1> Wrap method in a span.
+<2> Return a string.
+
+Let us call the _Outbound_ endpoint:
+
+[source,bash]
+----
+curl localhost:8080/greet/outbound
+Secondary
+----
+
+The `greeting-service` call `secondary-service`. Each service will create Spans with corresponding names, and a service class hierarchy will be created.
+
+Launch the Jaeger UI at link:http://localhost:16686/[] to see the expected output (shown below).
+
+image::telemetry/telemetry-outbound-jaeger.png[Secondary service outbound call]
+
+
+== Additional Information
+
+
+== Reference
+
+* link:https://download.eclipse.org/microprofile/microprofile-telemetry-1.0/tracing/microprofile-telemetry-tracing-spec-1.0.pdf[MicroProfile Telemetry Specification]
+* link:https://opentelemetry.io/docs/[OpenTelemetry Documentation]
\ No newline at end of file
diff --git a/docs/nima/testing.adoc b/docs/nima/testing.adoc
new file mode 100644
index 00000000000..df2d2b05f9b
--- /dev/null
+++ b/docs/nima/testing.adoc
@@ -0,0 +1,393 @@
+///////////////////////////////////////////////////////////////////////////////
+
+ Copyright (c) 2023 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.
+
+///////////////////////////////////////////////////////////////////////////////
+
+= Helidon Níma Testing
+:h1Prefix: Níma
+:pagename: Helidon Níma Testing
+:description: Testing in Helidon Níma
+:keywords: helidon, nima, test, testing, junit
+:feature-name: Helidon Níma Testing Framework
+:rootdir: {docdir}/..
+
+== Contents
+
+- <>
+- <>
+- <>
+- <>
+- <>
+- <>
+
+== Overview
+
+Helidon provides built-in test support for Helidon Níma testing with JUnit 5.
+
+include::{rootdir}/includes/dependencies.adoc[]
+[source,xml]
+----
+
+ io.helidon.nima.testing.junit5
+ helidon-nima-testing-junit5-webserver
+ test
+
+----
+
+== Usage
+
+Helidon provides a rich set of extensions based on JUnit 5 for Helidon Níma testing. Testing can be done with automatic server start-up, configuration, and shutdown. Testing can also be done without full server start-up with `DirectClient` when no real sockets are created.
+
+== API
+
+There are two main annotations that you can use to test the Níma server.
+
+* `@ServerTest` is an integration test annotation that starts the server (opens ports) and provides client injection pre-configured for the server port(s).
+* `@RoutingTest` is a unit test annotation that does not start the server and does not open ports but provides a direct client (with the same API as the usual network client) to test routing.
+
+The additional annotation `@Socket` can be used to qualify the injection of parameters into test constructors or methods, such as to obtain a client configured for the named socket.
+
+The following table lists the supported types of parameters for the `@SetUpRoute` annotated methods. Such methods MUST be static
+and may have any name. The `@SetUpRoute` annotation has `value` with socket name (to customize the setup for a different socket).
+
+- Parameter type - supported class of a parameter
+- Annotation - which annotations support this parameter
+- Modules - which Níma extension modules support this signature
+
+.Parameters for the `@SetUpRoute` annotated methods.
+|===
+|Parameter Type |Annotation |Modules |Notes
+
+|`HttpRouting.Builder`
+|`@ServerTest`, `@RoutingTest`
+|
+|
+
+|`HttpRules`
+|`@ServerTest`, `@RoutingTest`
+|
+|Same as `HttpRouting.Builder`, only routing setup
+
+|`Router.RouterBuilder>`
+|`@ServerTest`, `@RoutingTest`
+|
+|
+
+|`SocketListener.Builder`
+|`@ServerTest`
+|
+|
+
+|`WebSocketRouting.Builder`
+|`@ServerTest`, `@RoutingTest`
+|websocket
+|
+
+|===
+
+In addition, a static method annotated with `@SetUpServer` can be defined for `@ServerTest`, which has a single parameter of `WebServer.Builder`.
+
+The following table lists the injectable types (through constructor or method injection).
+
+- Type - type that can be injected
+- Socket - if checked, you can use the `@Socket` annotation to obtain a value specific to that named socket
+- Annotation - which annotations support this injection
+- Modules - which Níma extension modules support this injection
+- Notes - additional details
+
+.Injectable types.
+|===
+|Type |Socket? |Annotation |Modules |Notes
+|`WebServer`
+|
+|`@ServerTest`
+|
+|Server instance (already started)
+
+|`URI`
+|x
+|`@ServerTest`
+|
+|URI pointing to a port of the webserver
+
+|`SocketHttpClient`
+|x
+|`@ServerTest`
+|
+|This client allows you to send anything in order to test for bad requests or other issues.
+
+|`Http1Client`
+|x
+|`@ServerTest`
+|
+|
+
+|`DirectClient`
+|x
+|`@RoutingTest`
+|
+|Implements `Http1Client` API
+
+|`WsClient`
+|x
+|`@ServerTest`
+|websocket
+|
+
+|`DirectWsClient`
+|x
+|`@RoutingTest`
+|websocket
+|Implements `WsClient` API
+
+|===
+
+
+Extensions can enhance the features for the module `helidon-nima-testing-junit5-webserver` to support additional protocols.
+
+
+== Examples
+
+You can create the following test to validate that the server returns the correct response:
+
+.Basic Helidon Níma test framework usage.
+[source, java]
+----
+@ServerTest <1>
+class IntegrationTest {
+
+ private final Http1Client client;
+
+ protected IntegrationTest(Http1Client client) { <2>
+ this.client = client;
+ }
+
+ @SetUpRoute <3>
+ static void routing(HttpRouting.Builder builder) {
+ QuickstartMain.routing(builder);
+ }
+
+ @Test <4>
+ void testRootRoute() {
+ try (Http1ClientResponse response = client.get("/greet")
+ .request()) { <5>
+
+ assertThat(response.status(), is(Http.Status.OK_200)); <6>
+ }
+ }
+}
+----
+<1> Use `@ServerTest` to trigger the testing framework.
+<2> Inject `Http1Client` for the test.
+<3> SetUp routing for the test.
+<4> Regular `JUnit` test method.
+<5> Call the `client` to obtain server response
+<6> Perform the necessary assertions.
+
+To trigger the framework to start and configure the Níma server, annotate the testing class with the `@ServerTest` annotation.
+
+In this test, the `Http1Client` client is used, which means that the framework will create, configure, and inject this object as a parameter to the constructor.
+
+To set up routing, a static method annotated with `@SetUpRoute` is present. The framework uses this method to inject the configured routing to the subject of testing – in the current case, the `Quickstart` application.
+
+As everything above is performed by the testing framework, regular unit tests can be done. After completing all tests, the testing framework will shut down the Níma server.
+
+=== Routing Tests
+
+If there is no need to set up and run a server, a `DirectClient` client can be used. It is a testing client that bypasses HTTP transport and directly invokes the router.
+
+.Routing test using `@RoutingTest` and `DirectClient`.
+[source, java]
+----
+@RoutingTest <1>
+class RoutingTest {
+
+ private final Http1Client client;
+
+ protected RoutingTest(DirectClient client) { <2>
+ this.client = client;
+ }
+
+ @SetUpRoute <3>
+ static void routing(HttpRouting.Builder builder) {
+ QuickstartMain.routing(builder);
+ }
+
+ @Test <4>
+ void testRootRoute() {
+ try (Http1ClientResponse response = client.get("/greet")
+ .request()) { <5>
+
+ JsonObject json = response.as(JsonObject.class); <6>
+ assertThat(json.getString("message"), is("Hello World!"));
+ }
+ }
+}
+----
+<1> Use `@RoutingTest` to trigger the testing framework.
+<2> Inject `DirectClient` for the test.
+<3> SetUp routing for the test.
+<4> A regular `JUnit` test method.
+<5> Call the `client` to obtain server response.
+<6> Perform the necessary assertions.
+
+If only routing tests are required, this is a "lighter" way of testing because the framework will not configure and run the full Níma server. This way, no real ports will be opened. All the communication will be done through `DirectClient`, which makes the tests very effective.
+
+It is required to annotate the test class with the `@RoutingTest` annotation to trigger the server to do the configuration. Thus, it will inject the DirectClient client, which can then be used in unit tests.
+
+Routing is configured the same way as in full server testing using the `@SetUpRoute` annotation.
+
+== Additional Information
+
+=== WebSocket Testing
+
+If WebSocket testing is required, there is an additional module for it. It is necessary to include the following Maven dependency to the Project's pom file:
+
+[source,xml]
+----
+
+ io.helidon.nima.testing.junit5
+ helidon-nima-testing-junit5-websocket
+ test
+
+----
+
+
+=== WebSocket Testing Example
+
+The WebSocket Testing extension adds support for routing configuration and injection of WebSocket related artifacts, such as WebSockets and DirectWsClient in Helidon Níma unit tests.
+
+.WebSocket sample test.
+[source,java]
+----
+@ServerTest
+class WsSocketTest {
+
+ private static final ServerSideListener WS_LISTENER = new ServerSideListener();
+
+ private final WsClient wsClient; <1>
+
+ protected WsSocketTest(WsClient wsClient) {
+ this.wsClient = wsClient;
+ }
+
+ @SetUpRoute
+ static void routing(WsRouting.Builder ws) { <2>
+ ws.endpoint("/testWs", WS_LISTENER);
+ }
+
+ @Test
+ void testWsEndpoint() { <3>
+ WS_LISTENER.reset();
+
+ ClientSideListener clientListener = new ClientSideListener();
+ wsClient.connect("/testWs", clientListener); <4>
+
+ assertThat(clientListener.message, is("ws")); <5>
+ }
+}
+----
+<1> Declare `WsClient` and later inject it in the constructor.
+<2> Using @SetUpRoute, create WebSocket routing and assign a serverside listener.
+<3> Test the WebSocket endpoint using the regular @Test annotation.
+<4> Create and assign the clientside listener.
+<5> Check if the received message is correct.
+
+[NOTE]
+====
+The WebSocket `ClientSideListener` is a helper class that implements `WsListener`. `ClientSideListener` is very simple and looks as follows:
+
+.`ClientSideListener` helper class.
+[source,java]
+----
+private static class ClientSideListener implements WsListener {
+ private final CountDownLatch cdl = new CountDownLatch(1);
+ private String message;
+ private volatile Throwable throwable;
+
+ @Override
+ public void onOpen(WsSession session) { <1>
+ session.send("hello", true);
+ }
+
+ @Override
+ public void onMessage(WsSession session, String text, boolean last) { <2>
+ this.message = text;
+ session.close(WsCloseCodes.NORMAL_CLOSE, "End");
+ }
+
+ @Override
+ public void onClose(WsSession session, int status, String reason) { <3>
+ cdl.countDown();
+ }
+
+ @Override
+ public void onError(WsSession session, Throwable t) { <4>
+ this.throwable = t;
+ cdl.countDown();
+ }
+}
+----
+<1> Send "Hello" when a connection is opened.
+<2> Save the message when received and close the connection.
+<3> Close the connection.
+<4> React on an error.
+
+The WebSocket `ClientSideListener` is also a helper class that implements `WsListener` and is very straightforward:
+
+.`ServerSideListener` helper class.
+[source,java]
+----
+private static class ServerSideListener implements WsListener {
+ boolean opened;
+ boolean closed;
+ String message;
+
+ @Override
+ public void onMessage(WsSession session, String text, boolean last) { <1>
+ message = text;
+ session.send("ws", true);
+ }
+
+ @Override
+ public void onClose(WsSession session, int status, String reason) { <2>
+ closed = true;
+ }
+
+ @Override
+ public void onOpen(WsSession session) { <3>
+ opened = true;
+ }
+
+ void reset() { <4>
+ opened = false;
+ closed = false;
+ message = null;
+ }
+}
+----
+<1> Send "ws" on a received message.
+<2> Called when the connection is called.
+<3> Called on connection is opened.
+<4> Used to reset the state.
+====
+
+The testing class should be annotated with `@RoutingTest` only if routing tests are required without real port opening. Instead of `WsClient`, use `DirectWsClient`.
+
+
+== Reference
+
+* https://junit.org/junit5/docs/current/user-guide/[JUnit 5 User Guide]
diff --git a/docs/se/integrations/neo4j.adoc b/docs/se/integrations/neo4j.adoc
index 7faad4177c6..b2e2156b6c5 100644
--- a/docs/se/integrations/neo4j.adoc
+++ b/docs/se/integrations/neo4j.adoc
@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
- Copyright (c) 2022 Oracle and/or its affiliates.
+ Copyright (c) 2022, 2023 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.
@@ -221,7 +221,7 @@ private static Routing createRouting(Config config) {
HealthSupport health = HealthSupport.builder()
.add(HealthChecks.healthChecks()) // Adds a convenient set of checks
- .addReadiness(healthCheck)
+ .add(healthCheck)
.build();
return Routing.builder() // <5>
@@ -329,7 +329,7 @@ To enable health checks run the following code:
Neo4jHealthCheck healthCheck = Neo4jHealthCheck.create(neo4j.driver());
HealthSupport health = HealthSupport.builder()
- .addReadiness(healthCheck)
+ .add(healthCheck)
.build();
----
diff --git a/docs/se/openapi.adoc b/docs/se/openapi.adoc
index 804a06e8637..7b2b52ae1bb 100644
--- a/docs/se/openapi.adoc
+++ b/docs/se/openapi.adoc
@@ -38,7 +38,7 @@ include::{rootdir}/includes/se.adoc[]
== Overview
-include::{rootdir}/includes/openapi.adoc[tag=overview]
+include::{rootdir}/includes/openapi/openapi.adoc[tag=overview]
include::{rootdir}/includes/dependencies.adoc[]
@@ -62,7 +62,7 @@ the OpenAPI document for your application at runtime.
Helidon SE provides the link:{openapi-javadoc-base-url}/OpenAPISupport.html[`OpenAPISupport`] class which your application uses to assemble the in-memory model and expose the `/openapi` endpoint to clients. You can create an instance either using a static `create` method or by instantiating its link:{openapi-javadoc-base-url}/OpenAPISupport.Builder.html[`Builder`]. The xref:#register_openapisupport[example below] illustrates one way to do this.
-include::{rootdir}/includes/openapi.adoc[tag=furnish-openapi-info]
+include::{rootdir}/includes/openapi/openapi.adoc[tag=furnish-openapi-info]
==== Add OpenAPI dependency
If you implement either a model reader or a filter, add this dependency to your
@@ -77,11 +77,11 @@ If you implement either a model reader or a filter, add this dependency to your
----
-include::{rootdir}/includes/openapi.adoc[tag=usage-access-endpoint]
+include::{rootdir}/includes/openapi/openapi.adoc[tag=usage-access-endpoint]
== API
-include::{rootdir}/includes/openapi.adoc[tag=api]
+include::{rootdir}/includes/openapi/openapi.adoc[tag=api]
Helidon {flavor-uc} provides an API for creating and setting up the REST endpoint which serves OpenAPI documents to clients at the `/openapi` path. Use either static methods on link:{openapi-javadoc-base-url}/OpenAPISupport.html[`OpenAPISupport`] or use its link:{openapi-javadoc-base-url}/OpenAPISupport.Builder.html[`Builder`] to create an instance of `OpenAPISupport`. Then add that instance to your application's routing. The <<#register_openapisupport,example>> below shows how to do this.
@@ -120,4 +120,4 @@ return Routing.builder()
If you need more control over the `OpenAPISupport` instance, invoke `OpenAPISupport.builder()` to get an `OpenAPISupport.Builder` object and work with it.
== Additional Information
-include::{rootdir}/includes/openapi.adoc[tag=additional-building-jandex]
\ No newline at end of file
+include::{rootdir}/includes/openapi/openapi.adoc[tag=additional-building-jandex]
\ No newline at end of file
diff --git a/etc/checkstyle-suppressions.xml b/etc/checkstyle-suppressions.xml
index 1f2c11c3f36..04c6792b6d4 100644
--- a/etc/checkstyle-suppressions.xml
+++ b/etc/checkstyle-suppressions.xml
@@ -104,6 +104,8 @@
checks=".*"/>
+
+
+ io.helidon.nima.webserver
+ helidon-nima-webserver
+
+
+ io.helidon.nima.observe
+ helidon-nima-observe-health
+ io.helidon.examples.grpchelidon-examples-grpc-common
diff --git a/examples/grpc/basics/src/main/java/io/helidon/grpc/examples/basics/Server.java b/examples/grpc/basics/src/main/java/io/helidon/grpc/examples/basics/Server.java
index a42eba1aefc..f78094cf357 100644
--- a/examples/grpc/basics/src/main/java/io/helidon/grpc/examples/basics/Server.java
+++ b/examples/grpc/basics/src/main/java/io/helidon/grpc/examples/basics/Server.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2019, 2023 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.
@@ -23,11 +23,10 @@
import io.helidon.grpc.server.GrpcRouting;
import io.helidon.grpc.server.GrpcServer;
import io.helidon.grpc.server.GrpcServerConfiguration;
-import io.helidon.health.checks.HealthChecks;
import io.helidon.logging.common.LogConfig;
-import io.helidon.reactive.health.HealthSupport;
-import io.helidon.reactive.webserver.Routing;
-import io.helidon.reactive.webserver.WebServer;
+import io.helidon.nima.observe.ObserveFeature;
+import io.helidon.nima.webserver.WebServer;
+import io.helidon.nima.webserver.http.HttpRouting;
/**
* A basic example of a Helidon gRPC server.
@@ -53,7 +52,7 @@ public static void main(String[] args) {
GrpcServerConfiguration serverConfig =
GrpcServerConfiguration.builder(config.get("grpc")).build();
- GrpcServer grpcServer = GrpcServer.create(serverConfig, createRouting(config));
+ GrpcServer grpcServer = GrpcServer.create(serverConfig, createGrpcRouting(config));
// Try to start the server. If successful, print some info and arrange to
// print a message at shutdown. If unsuccessful, print the exception.
@@ -68,31 +67,18 @@ public static void main(String[] args) {
return null;
});
- // add support for standard and gRPC health checks
- HealthSupport health = HealthSupport.builder()
- .add(HealthChecks.healthChecks())
- .addLiveness(grpcServer.healthChecks())
- .build();
+ WebServer server = WebServer.builder()
+ .routing(Server::routing)
+ .start();
- // start web server with health endpoint
- Routing routing = Routing.builder()
- .register(health)
- .build();
+ System.out.println("WEB server is up! http://localhost:" + server.port());
+ }
- WebServer.create(routing, config.get("webserver"))
- .start()
- .thenAccept(s -> {
- System.out.println("HTTP server is UP! http://localhost:" + s.port());
- s.whenShutdown().thenRun(() -> System.out.println("HTTP server is DOWN. Good bye!"));
- })
- .exceptionally(t -> {
- System.err.println("Startup failed: " + t.getMessage());
- t.printStackTrace(System.err);
- return null;
- });
+ private static void routing(HttpRouting.Builder routing) {
+ routing.addFeature(ObserveFeature.create());
}
- private static GrpcRouting createRouting(Config config) {
+ private static GrpcRouting createGrpcRouting(Config config) {
GreetService greetService = new GreetService(config);
GreetServiceJava greetServiceJava = new GreetServiceJava(config);
diff --git a/examples/grpc/microprofile/basic-client/pom.xml b/examples/grpc/microprofile/basic-client/pom.xml
index feb56f87a33..bf9374cd73e 100644
--- a/examples/grpc/microprofile/basic-client/pom.xml
+++ b/examples/grpc/microprofile/basic-client/pom.xml
@@ -51,7 +51,7 @@
helidon-microprofile-grpc-client
- org.jboss
+ io.smallryejandexruntimetrue
@@ -70,7 +70,7 @@
- org.jboss.jandex
+ io.smallryejandex-maven-plugin
diff --git a/examples/grpc/microprofile/basic-server-implicit/pom.xml b/examples/grpc/microprofile/basic-server-implicit/pom.xml
index b2bc5b7fbd8..7a648112726 100644
--- a/examples/grpc/microprofile/basic-server-implicit/pom.xml
+++ b/examples/grpc/microprofile/basic-server-implicit/pom.xml
@@ -55,7 +55,7 @@
helidon-microprofile-grpc-client
- org.jboss
+ io.smallryejandexruntimetrue
@@ -74,7 +74,7 @@
- org.jboss.jandex
+ io.smallryejandex-maven-plugin
diff --git a/examples/grpc/microprofile/metrics/pom.xml b/examples/grpc/microprofile/metrics/pom.xml
index f75a28384f0..1352fb3c4f9 100644
--- a/examples/grpc/microprofile/metrics/pom.xml
+++ b/examples/grpc/microprofile/metrics/pom.xml
@@ -59,7 +59,7 @@
helidon-microprofile-grpc-client
- org.jboss
+ io.smallryejandexruntimetrue
@@ -78,7 +78,7 @@
- org.jboss.jandex
+ io.smallryejandex-maven-plugin
diff --git a/examples/grpc/security-abac/src/main/java/io/helidon/grpc/examples/security/abac/AtnProvider.java b/examples/grpc/security-abac/src/main/java/io/helidon/grpc/examples/security/abac/AtnProvider.java
index 5c3febccd5e..fbc99b198fc 100644
--- a/examples/grpc/security-abac/src/main/java/io/helidon/grpc/examples/security/abac/AtnProvider.java
+++ b/examples/grpc/security-abac/src/main/java/io/helidon/grpc/examples/security/abac/AtnProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2021 Oracle and/or its affiliates.
+ * Copyright (c) 2019, 2023 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.
@@ -44,12 +44,11 @@
import io.helidon.security.Subject;
import io.helidon.security.SubjectType;
import io.helidon.security.spi.AuthenticationProvider;
-import io.helidon.security.spi.SynchronousProvider;
/**
* Example authentication provider that reads annotation to create a subject.
*/
-public class AtnProvider extends SynchronousProvider implements AuthenticationProvider {
+public class AtnProvider implements AuthenticationProvider {
/**
* The configuration key for this provider.
@@ -63,7 +62,7 @@ private AtnProvider(Config config) {
}
@Override
- protected AuthenticationResponse syncAuthenticate(ProviderRequest providerRequest) {
+ public AuthenticationResponse authenticate(ProviderRequest providerRequest) {
EndpointConfig endpointConfig = providerRequest.endpointConfig();
Config atnConfig = endpointConfig.config(CONFIG_KEY).orElse(null);
Subject user = null;
diff --git a/examples/grpc/security-outbound/src/main/java/io/helidon/grpc/examples/security/outbound/SecureServer.java b/examples/grpc/security-outbound/src/main/java/io/helidon/grpc/examples/security/outbound/SecureServer.java
index b52c9131add..cd227f9aece 100644
--- a/examples/grpc/security-outbound/src/main/java/io/helidon/grpc/examples/security/outbound/SecureServer.java
+++ b/examples/grpc/security-outbound/src/main/java/io/helidon/grpc/examples/security/outbound/SecureServer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2019, 2023 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.
@@ -121,9 +121,9 @@ private static GrpcServer createGrpcServer(Config config, Security security) {
private static WebServer createWebServer(Config config, Security security) {
Routing routing = Routing.builder()
- .register(WebSecurity.create(security).securityDefaults(WebSecurity.authenticate()))
- .register(new RestService())
- .build();
+ .register(WebSecurity.create(security).securityDefaults(WebSecurity.authenticate()))
+ .register(new RestService())
+ .build();
WebServer webServer = WebServer.create(routing, config);
diff --git a/examples/health/basics/pom.xml b/examples/health/basics/pom.xml
index eba56e83721..36414b3ff33 100644
--- a/examples/health/basics/pom.xml
+++ b/examples/health/basics/pom.xml
@@ -39,16 +39,16 @@
- io.helidon.reactive.health
- helidon-reactive-health
+ io.helidon.nima.webserver
+ helidon-nima-webserver
- io.helidon.health
- helidon-health-checks
+ io.helidon.nima.observe
+ helidon-nima-observe-health
- io.helidon.reactive.webserver
- helidon-reactive-webserver
+ io.helidon.health
+ helidon-health-checksorg.junit.jupiter
diff --git a/examples/health/basics/src/main/java/io/helidon/examples/health/basics/Main.java b/examples/health/basics/src/main/java/io/helidon/examples/health/basics/Main.java
index f643fede6af..e8ed67ff06d 100644
--- a/examples/health/basics/src/main/java/io/helidon/examples/health/basics/Main.java
+++ b/examples/health/basics/src/main/java/io/helidon/examples/health/basics/Main.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2018, 2023 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.
@@ -17,12 +17,14 @@
import java.time.Duration;
-import io.helidon.health.checks.HealthChecks;
-import io.helidon.reactive.health.HealthSupport;
-import io.helidon.reactive.webserver.Routing;
-import io.helidon.reactive.webserver.WebServer;
-
-import org.eclipse.microprofile.health.HealthCheckResponse;
+import io.helidon.health.HealthCheckResponse;
+import io.helidon.health.HealthCheckType;
+import io.helidon.logging.common.LogConfig;
+import io.helidon.nima.observe.ObserveFeature;
+import io.helidon.nima.observe.health.HealthFeature;
+import io.helidon.nima.observe.health.HealthObserveProvider;
+import io.helidon.nima.webserver.WebServer;
+import io.helidon.nima.webserver.http.HttpRouting;
/**
* Main class of health check integration example.
@@ -41,33 +43,42 @@ private Main() {
*/
public static void main(String[] args) {
serverStartTime = System.currentTimeMillis();
- HealthSupport health = HealthSupport.builder()
- .add(HealthChecks.healthChecks())
- .addReadiness(() -> HealthCheckResponse.named("exampleHealthCheck")
- .up()
- .withData("time", System.currentTimeMillis())
- .build())
- .addStartup(() -> HealthCheckResponse.named("exampleStartCheck")
- .status(isStarted())
- .withData("time", System.currentTimeMillis())
- .build())
- .build();
- Routing routing = Routing.builder()
- .register(health)
- .get("/hello", (req, res) -> res.send("Hello World!"))
- .build();
+ // load logging
+ LogConfig.configureRuntime();
+
+ WebServer server = WebServer.builder()
+ .routing(Main::routing)
+ .start();
+
+ System.out.println("WEB server is up! http://localhost:" + server.port());
+ }
- WebServer ws = WebServer.create(routing);
+ /**
+ * Set up HTTP routing.
+ * This method is used from tests as well.
+ *
+ * @param router HTTP routing builder
+ */
+ static void routing(HttpRouting.Builder router) {
+ ObserveFeature observe = ObserveFeature.builder()
+ .useSystemServices(true)
+ .addProvider(HealthObserveProvider.create(HealthFeature.builder()
+ .useSystemServices(true)
+ .addCheck(() -> HealthCheckResponse.builder()
+ .status(HealthCheckResponse.Status.UP)
+ .detail("time", System.currentTimeMillis())
+ .build(), HealthCheckType.READINESS)
+ .addCheck(() -> HealthCheckResponse.builder()
+ .status(isStarted())
+ .detail("time", System.currentTimeMillis())
+ .build(), HealthCheckType.STARTUP)
+ .build()))
+ .build();
- ws.start()
- .thenApply(webServer -> {
- String endpoint = "http://localhost:" + webServer.port();
- System.out.println("Hello World started on " + endpoint + "/hello");
- System.out.println("Health checks available on " + endpoint + "/health");
- return null;
- });
+ router.get("/hello", (req, res) -> res.send("Hello World!"))
+ .addFeature(observe);
}
private static boolean isStarted() {
diff --git a/examples/integrations/cdi/datasource-hikaricp-h2/pom.xml b/examples/integrations/cdi/datasource-hikaricp-h2/pom.xml
index b8d580908d6..d4d05758adf 100644
--- a/examples/integrations/cdi/datasource-hikaricp-h2/pom.xml
+++ b/examples/integrations/cdi/datasource-hikaricp-h2/pom.xml
@@ -61,7 +61,7 @@
runtime
- org.jboss
+ io.smallryejandexruntimetrue
@@ -90,7 +90,7 @@
- org.jboss.jandex
+ io.smallryejandex-maven-plugin
diff --git a/examples/integrations/cdi/datasource-hikaricp-mysql/pom.xml b/examples/integrations/cdi/datasource-hikaricp-mysql/pom.xml
index a9b1814c5e4..c802b4e21fa 100644
--- a/examples/integrations/cdi/datasource-hikaricp-mysql/pom.xml
+++ b/examples/integrations/cdi/datasource-hikaricp-mysql/pom.xml
@@ -62,7 +62,7 @@
runtime
- org.jboss
+ io.smallryejandexruntimetrue
@@ -91,7 +91,7 @@
- org.jboss.jandex
+ io.smallryejandex-maven-plugin
diff --git a/examples/integrations/cdi/datasource-hikaricp/pom.xml b/examples/integrations/cdi/datasource-hikaricp/pom.xml
index 7c84fc34e56..c2850ca4680 100644
--- a/examples/integrations/cdi/datasource-hikaricp/pom.xml
+++ b/examples/integrations/cdi/datasource-hikaricp/pom.xml
@@ -67,7 +67,7 @@
runtime
- org.jboss
+ io.smallryejandexruntimetrue
@@ -96,7 +96,7 @@
- org.jboss.jandex
+ io.smallryejandex-maven-plugin
diff --git a/examples/integrations/cdi/jedis/pom.xml b/examples/integrations/cdi/jedis/pom.xml
index 16dddf17592..02fb490a043 100644
--- a/examples/integrations/cdi/jedis/pom.xml
+++ b/examples/integrations/cdi/jedis/pom.xml
@@ -60,7 +60,7 @@
runtime
- org.jboss
+ io.smallryejandexruntimetrue
@@ -89,7 +89,7 @@
- org.jboss.jandex
+ io.smallryejandex-maven-plugin
diff --git a/examples/integrations/cdi/jpa/pom.xml b/examples/integrations/cdi/jpa/pom.xml
index 934d875f47a..359982a67ee 100644
--- a/examples/integrations/cdi/jpa/pom.xml
+++ b/examples/integrations/cdi/jpa/pom.xml
@@ -92,7 +92,7 @@
runtime
- org.jboss
+ io.smallryejandexruntimetrue
@@ -152,7 +152,7 @@
- org.jboss.jandex
+ io.smallryejandex-maven-plugin
diff --git a/examples/integrations/cdi/pokemons/pom.xml b/examples/integrations/cdi/pokemons/pom.xml
index 9525d81bc49..ecae02349fe 100644
--- a/examples/integrations/cdi/pokemons/pom.xml
+++ b/examples/integrations/cdi/pokemons/pom.xml
@@ -90,7 +90,7 @@
runtime
- org.jboss
+ io.smallryejandexruntimetrue
@@ -151,7 +151,7 @@
- org.jboss.jandex
+ io.smallryejandex-maven-plugin
diff --git a/examples/integrations/micrometer/mp/pom.xml b/examples/integrations/micrometer/mp/pom.xml
index c523c2de060..78ffa4d105e 100644
--- a/examples/integrations/micrometer/mp/pom.xml
+++ b/examples/integrations/micrometer/mp/pom.xml
@@ -87,7 +87,7 @@
- org.jboss.jandex
+ io.smallryejandex-maven-plugin
diff --git a/examples/integrations/micronaut/data/pom.xml b/examples/integrations/micronaut/data/pom.xml
index 499160e2025..d53c303aafd 100644
--- a/examples/integrations/micronaut/data/pom.xml
+++ b/examples/integrations/micronaut/data/pom.xml
@@ -79,7 +79,7 @@
runtime
- org.jboss
+ io.smallryejandexruntimetrue
@@ -144,7 +144,7 @@
- org.jboss.jandex
+ io.smallryejandex-maven-plugin
diff --git a/examples/integrations/microstream/greetings-mp/pom.xml b/examples/integrations/microstream/greetings-mp/pom.xml
index 60afd4b4ecd..320cfd01226 100644
--- a/examples/integrations/microstream/greetings-mp/pom.xml
+++ b/examples/integrations/microstream/greetings-mp/pom.xml
@@ -70,7 +70,7 @@
- org.jboss.jandex
+ io.smallryejandex-maven-plugin
diff --git a/examples/integrations/microstream/greetings-mp/src/test/java/io/helidon/examples/integrations/microstream/greetings/mp/MicrostreamExampleGreetingsMpTest.java b/examples/integrations/microstream/greetings-mp/src/test/java/io/helidon/examples/integrations/microstream/greetings/mp/MicrostreamExampleGreetingsMpTest.java
index 59945fc6240..3ae71957af4 100644
--- a/examples/integrations/microstream/greetings-mp/src/test/java/io/helidon/examples/integrations/microstream/greetings/mp/MicrostreamExampleGreetingsMpTest.java
+++ b/examples/integrations/microstream/greetings-mp/src/test/java/io/helidon/examples/integrations/microstream/greetings/mp/MicrostreamExampleGreetingsMpTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Oracle and/or its affiliates.
+ * Copyright (c) 2021, 2023 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.
@@ -31,8 +31,6 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
@HelidonTest
-@Disabled("3.0.0-JAKARTA") // OpenAPI
-// Caused by: java.lang.NoSuchMethodError: 'java.util.List org.jboss.jandex.ClassInfo.unsortedFields()'
class MicrostreamExampleGreetingsMpTest {
@Inject
diff --git a/examples/integrations/neo4j/README.md b/examples/integrations/neo4j/README.md
new file mode 100644
index 00000000000..d35611349cd
--- /dev/null
+++ b/examples/integrations/neo4j/README.md
@@ -0,0 +1,38 @@
+# Helidon SE integration with Neo4J example
+
+## Build and run
+
+Bring up a Neo4j instance via Docker
+
+```bash
+docker run --publish=7474:7474 --publish=7687:7687 -e 'NEO4J_AUTH=neo4j/secret' neo4j:4.0
+```
+
+Goto the Neo4j browser and play the first step of the movies graph: [`:play movies`](http://localhost:7474/browser/?cmd=play&arg=movies).
+
+Build and run with JDK20
+```bash
+mvn package
+java -jar target/helidon-examples-integration-neo4j-nima.jar
+```
+
+Then access the rest API like this:
+
+````
+curl localhost:8080/api/movies
+````
+
+# Health and metrics
+
+Neo4jSupport provides health checks and metrics reading from Neo4j.
+
+Enable them in the driver:
+```yaml
+ pool:
+ metricsEnabled: true
+```
+
+````
+curl localhost:8080/observe/health
+curl localhost:8080/observe/metrics
+````
diff --git a/examples/integrations/neo4j/neo4j-mp/.dockerignore b/examples/integrations/neo4j/neo4j-mp/.dockerignore
deleted file mode 100644
index c8b241f2215..00000000000
--- a/examples/integrations/neo4j/neo4j-mp/.dockerignore
+++ /dev/null
@@ -1 +0,0 @@
-target/*
\ No newline at end of file
diff --git a/examples/integrations/neo4j/neo4j-mp/Dockerfile b/examples/integrations/neo4j/neo4j-mp/Dockerfile
deleted file mode 100644
index 8eeb50924e4..00000000000
--- a/examples/integrations/neo4j/neo4j-mp/Dockerfile
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# Copyright (c) 2021 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.
-#
-
-# 1st stage, build the app
-FROM maven:3.6.3-openjdk-17-slim as build
-
-WORKDIR /helidon
-
-# Create a first layer to cache the "Maven World" in the local repository.
-# Incremental docker builds will always resume after that, unless you update
-# the pom
-ADD pom.xml .
-RUN mvn package -Dmaven.test.skip -Declipselink.weave.skip
-
-# Do the Maven build!
-# Incremental docker builds will resume here when you change sources
-ADD src src
-RUN mvn package -DskipTests
-RUN echo "done!"
-
-# 2nd stage, build the runtime image
-FROM openjdk:17-jdk-slim
-WORKDIR /helidon
-
-# Copy the binary built in the 1st stage
-COPY --from=build /helidon/target/helidon-examples-integration-neo4j-mp.jar ./
-COPY --from=build /helidon/target/libs ./libs
-
-CMD ["java", "-jar", "helidon-examples-integration-neo4j-mp.jar"]
-
-EXPOSE 8080
diff --git a/examples/integrations/neo4j/neo4j-mp/Dockerfile.jlink b/examples/integrations/neo4j/neo4j-mp/Dockerfile.jlink
deleted file mode 100644
index b011b1ebb35..00000000000
--- a/examples/integrations/neo4j/neo4j-mp/Dockerfile.jlink
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# Copyright (c) 2021, 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.
-#
-
-# 1st stage, build the app
-FROM maven:3.6.3-openjdk-17-slim as build
-
-WORKDIR /helidon
-
-# Create a first layer to cache the "Maven World" in the local repository.
-# Incremental docker builds will always resume after that, unless you update
-# the pom
-ADD pom.xml .
-RUN mvn package -Dmaven.test.skip -Declipselink.weave.skip
-
-# Do the Maven build to create the custom Java Runtime Image
-# Incremental docker builds will resume here when you change sources
-ADD src src
-RUN mvn package -Pjlink-image -DskipTests
-RUN echo "done!"
-
-# 2nd stage, build the final image with the JRI built in the 1st stage
-
-FROM debian:stretch-slim
-WORKDIR /helidon
-COPY --from=build /helidon/target/helidon-examples-integration-neo4j-mp-jri ./
-ENTRYPOINT ["/bin/bash", "/helidon/bin/start"]
-EXPOSE 8080
diff --git a/examples/integrations/neo4j/neo4j-mp/Dockerfile.native b/examples/integrations/neo4j/neo4j-mp/Dockerfile.native
deleted file mode 100644
index 403c9eba53e..00000000000
--- a/examples/integrations/neo4j/neo4j-mp/Dockerfile.native
+++ /dev/null
@@ -1,57 +0,0 @@
-#
-# Copyright (c) 2021, 2023 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.
-#
-
-# 1st stage, build the app
-FROM ghcr.io/graalvm/graalvm-ce:ol9-java20-22.3.1 as build
-
-# Install native-image
-RUN gu install native-image
-
-WORKDIR /usr/share
-
-# Install maven
-RUN set -x && \
- curl -O https://archive.apache.org/dist/maven/maven-3/3.8.4/binaries/apache-maven-3.8.4-bin.tar.gz && \
- tar -xvf apache-maven-*-bin.tar.gz && \
- rm apache-maven-*-bin.tar.gz && \
- mv apache-maven-* maven && \
- ln -s /usr/share/maven/bin/mvn /bin/
-
-WORKDIR /helidon
-
-# Create a first layer to cache the "Maven World" in the local repository.
-# Incremental docker builds will always resume after that, unless you update
-# the pom
-ADD pom.xml .
-RUN mvn package -Pnative-image -Dnative.image.skip -Dmaven.test.skip -Declipselink.weave.skip
-
-# Do the Maven build!
-# Incremental docker builds will resume here when you change sources
-ADD src src
-RUN mvn package -Pnative-image -Dnative.image.buildStatic -DskipTests
-
-RUN echo "done!"
-
-# 2nd stage, build the runtime image
-FROM scratch
-WORKDIR /helidon
-
-# Copy the binary built in the 1st stage
-COPY --from=build /helidon/target/helidon-examples-integration-neo4j-mp .
-
-ENTRYPOINT ["./helidon-examples-integration-neo4j-mp"]
-
-EXPOSE 8080
diff --git a/examples/integrations/neo4j/neo4j-mp/README.md b/examples/integrations/neo4j/neo4j-mp/README.md
deleted file mode 100644
index d925c4b2d94..00000000000
--- a/examples/integrations/neo4j/neo4j-mp/README.md
+++ /dev/null
@@ -1,167 +0,0 @@
-# Helidon Quickstart MP Example
-
-This example implements a simple Neo4j REST service using MicroProfile.
-
-## Build and run
-
-Bring up a Neo4j instance via Docker
-
-```bash
-docker run --publish=7474:7474 --publish=7687:7687 -e 'NEO4J_AUTH=neo4j/secret' neo4j:4.0
-```
-
-Goto the Neo4j browser and play the first step of the movies graph: [`:play movies`](http://localhost:7474/browser/?cmd=play&arg=movies).
-
-
-Then build with JDK11+
-```bash
-mvn package
-java -jar target/helidon-examples-integration-neo4j-mp.jar
-```
-
-## Exercise the application
-
-```
-curl -X GET http://localhost:8080/movies
-
-```
-
-## Try health and metrics
-
-```
-curl -s -X GET http://localhost:8080/health
-{"outcome":"UP",...
-. . .
-
-# Prometheus Format
-curl -s -X GET http://localhost:8080/metrics
-# TYPE base:gc_g1_young_generation_count gauge
-. . .
-
-# JSON Format
-curl -H 'Accept: application/json' -X GET http://localhost:8080/metrics
-{"base":...
-. . .
-
-```
-
-## Build the Docker Image
-
-```
-docker build -t helidon-integrations-neo4j-mp .
-```
-
-## Start the application with Docker
-
-```
-docker run --rm -p 8080:8080 helidon-integrations-neo4j-mp:latest
-```
-
-Exercise the application as described above
-
-## Deploy the application to Kubernetes
-
-```
-kubectl cluster-info # Verify which cluster
-kubectl get pods # Verify connectivity to cluster
-kubectl create -f app.yaml # Deploy application
-kubectl get service helidon-integrations-neo4j-mp # Verify deployed service
-```
-
-## Build a native image with GraalVM
-
-GraalVM allows you to compile your programs ahead-of-time into a native
- executable. See https://www.graalvm.org/docs/reference-manual/aot-compilation/
- for more information.
-
-You can build a native executable in 2 different ways:
-* With a local installation of GraalVM
-* Using Docker
-
-### Local build
-
-Download Graal VM at https://www.graalvm.org/downloads. We recommend
-version `20.1.0` or later.
-
-```
-# Setup the environment
-export GRAALVM_HOME=/path
-# build the native executable
-mvn package -Pnative-image
-```
-
-You can also put the Graal VM `bin` directory in your PATH, or pass
- `-DgraalVMHome=/path` to the Maven command.
-
-See https://github.com/oracle/helidon-build-tools/tree/master/helidon-maven-plugin#goal-native-image
- for more information.
-
-Start the application:
-
-```
-./target/helidon-quickstart-mp
-```
-
-### Multi-stage Docker build
-
-Build the "native" Docker Image
-
-```
-docker build -t helidon-integrations-neo4j-mp-native -f Dockerfile.native .
-```
-
-Start the application:
-
-```
-docker run --rm -p 8080:8080 helidon-integrations-neo4j-mp-native:latest
-```
-
-
-## Build a Java Runtime Image using jlink
-
-You can build a custom Java Runtime Image (JRI) containing the application jars and the JDK modules
-on which they depend. This image also:
-
-* Enables Class Data Sharing by default to reduce startup time.
-* Contains a customized `start` script to simplify CDS usage and support debug and test modes.
-
-You can build a custom JRI in two different ways:
-* Local
-* Using Docker
-
-
-### Local build
-
-```
-# build the JRI
-mvn package -Pjlink-image
-```
-
-See https://github.com/oracle/helidon-build-tools/tree/master/helidon-maven-plugin#goal-jlink-image
- for more information.
-
-Start the application:
-
-```
-./target/helidon-integrations-neo4j-mp-jri/bin/start
-```
-
-### Multi-stage Docker build
-
-Build the JRI as a Docker Image
-
-```
-docker build -t helidon-integrations-neo4j-mp-jri -f Dockerfile.jlink .
-```
-
-Start the application:
-
-```
-docker run --rm -p 8080:8080 helidon-integrations-neo4j-mp-jri:latest
-```
-
-See the start script help:
-
-```
-docker run --rm helidon-integrations-neo4j-mp-jri:latest --help
-```
diff --git a/examples/integrations/neo4j/neo4j-mp/app.yaml b/examples/integrations/neo4j/neo4j-mp/app.yaml
deleted file mode 100644
index 3359b178eef..00000000000
--- a/examples/integrations/neo4j/neo4j-mp/app.yaml
+++ /dev/null
@@ -1,50 +0,0 @@
-#
-# Copyright (c) 2021 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.
-#
-
-kind: Service
-apiVersion: v1
-metadata:
- name: helidon-examples-integration-neo4j-mp
- labels:
- app: helidon-examples-integration-neo4j-mp
-spec:
- type: NodePort
- selector:
- app: helidon-examples-integration-neo4j-mp
- ports:
- - port: 8080
- targetPort: 8080
- name: http
----
-kind: Deployment
-apiVersion: extensions/v1beta1
-metadata:
- name: helidon-examples-integration-neo4j-mp
-spec:
- replicas: 1
- template:
- metadata:
- labels:
- app: helidon-examples-integration-neo4j-mp
- version: v1
- spec:
- containers:
- - name: helidon-examples-integration-neo4j-mp
- image: helidon-examples-integration-neo4j-mp
- imagePullPolicy: IfNotPresent
- ports:
- - containerPort: 8080
----
diff --git a/examples/integrations/neo4j/neo4j-mp/pom.xml b/examples/integrations/neo4j/neo4j-mp/pom.xml
deleted file mode 100644
index 4916901140f..00000000000
--- a/examples/integrations/neo4j/neo4j-mp/pom.xml
+++ /dev/null
@@ -1,141 +0,0 @@
-
-
-
-
- 4.0.0
-
- io.helidon.applications
- helidon-mp
- 4.0.0-SNAPSHOT
- ../../../../applications/mp/pom.xml
-
- io.helidon.examples.integrations.neo4j
- helidon-examples-integration-neo4j-mp
- Helidon Neo4j MP integration Example
-
-
- 4.4.3
-
-
-
-
- io.helidon.microprofile.bundles
- helidon-microprofile
-
-
- io.helidon.integrations.neo4j
- helidon-integrations-neo4j
-
-
- io.helidon.integrations.neo4j
- helidon-integrations-neo4j-metrics
-
-
- io.helidon.integrations.neo4j
- helidon-integrations-neo4j-health
-
-
-
-
- org.jboss
- jandex
- runtime
- true
-
-
-
-
-
- org.neo4j.test
- neo4j-harness
- ${neo4j-harness.version}
- test
-
-
- org.slf4j
- slf4j-nop
-
-
- org.junit.vintage
- junit-vintage-engine
-
-
- org.neo4j.app
- neo4j-server
-
-
-
-
- org.neo4j.app
- neo4j-server
- ${neo4j-harness.version}
- test
-
-
- *
- *
-
-
-
-
- org.junit.jupiter
- junit-jupiter-api
- test
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- copy-libs
-
-
-
-
- org.jboss.jandex
- jandex-maven-plugin
-
-
- make-index
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
-
- --add-opens=java.base/java.lang=ALL-UNNAMED
-
-
-
-
-
-
diff --git a/examples/integrations/neo4j/neo4j-mp/src/main/java/io/helidon/examples/integrations/neo4j/mp/Neo4jResource.java b/examples/integrations/neo4j/neo4j-mp/src/main/java/io/helidon/examples/integrations/neo4j/mp/Neo4jResource.java
deleted file mode 100644
index c35b4d33d93..00000000000
--- a/examples/integrations/neo4j/neo4j-mp/src/main/java/io/helidon/examples/integrations/neo4j/mp/Neo4jResource.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2021 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.examples.integrations.neo4j.mp;
-
-import java.util.List;
-
-import io.helidon.examples.integrations.neo4j.mp.domain.Movie;
-import io.helidon.examples.integrations.neo4j.mp.domain.MovieRepository;
-
-import jakarta.enterprise.context.RequestScoped;
-import jakarta.inject.Inject;
-import jakarta.ws.rs.GET;
-import jakarta.ws.rs.Path;
-import jakarta.ws.rs.Produces;
-import jakarta.ws.rs.core.MediaType;
-
-/**
- * REST endpoint for movies.
- */
-@Path("/movies")
-@RequestScoped
-public class Neo4jResource {
- /**
- * The greeting message provider.
- */
- private final MovieRepository movieRepository;
-
- /**
- * Constructor.
- *
- * @param movieRepository
- */
- @Inject
- public Neo4jResource(MovieRepository movieRepository) {
- this.movieRepository = movieRepository;
- }
-
- /**
- * All movies.
- *
- * @return json String with all movies
- */
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- public List getAllMovies() {
- return movieRepository.findAll();
- }
-
-}
-
diff --git a/examples/integrations/neo4j/neo4j-mp/src/main/java/io/helidon/examples/integrations/neo4j/mp/domain/Actor.java b/examples/integrations/neo4j/neo4j-mp/src/main/java/io/helidon/examples/integrations/neo4j/mp/domain/Actor.java
deleted file mode 100644
index 4b821668180..00000000000
--- a/examples/integrations/neo4j/neo4j-mp/src/main/java/io/helidon/examples/integrations/neo4j/mp/domain/Actor.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2002-2020 "Neo4j,"
- * Neo4j Sweden AB [http://neo4j.com]
- * This file is part of Neo4j.
- * 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.examples.integrations.neo4j.mp.domain;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/*
- * Helidon changes are under the copyright of:
- *
- * Copyright (c) 2021, 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.
- *
- */
-
-/**
- * The Actor class.
- *
- * @author Michael Simons
- */
-public class Actor {
-
- private final String name;
-
- private final List roles;
-
- /**
- * Constructor.
- *
- * @param name
- * @param roles
- */
- public Actor(String name, final List roles) {
- this.name = name;
- this.roles = new ArrayList<>(roles);
- }
-}
diff --git a/examples/integrations/neo4j/neo4j-mp/src/main/java/io/helidon/examples/integrations/neo4j/mp/domain/Movie.java b/examples/integrations/neo4j/neo4j-mp/src/main/java/io/helidon/examples/integrations/neo4j/mp/domain/Movie.java
deleted file mode 100644
index 7d1abcd1455..00000000000
--- a/examples/integrations/neo4j/neo4j-mp/src/main/java/io/helidon/examples/integrations/neo4j/mp/domain/Movie.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2002-2020 "Neo4j,"
- * Neo4j Sweden AB [http://neo4j.com]
- * This file is part of Neo4j.
- * 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.examples.integrations.neo4j.mp.domain;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/*
- * Helidon changes are under the copyright of:
- *
- * Copyright (c) 2021, 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.
- *
- */
-/**
- * The Movie class.
- *
- * @author Michael Simons
- */
-public class Movie {
-
- private final String title;
-
- private final String description;
-
- private List actors = new ArrayList<>();
-
- private List directors = new ArrayList<>();
-
- private Integer released;
-
- /**
- * Constructor.
- *
- * @param title
- * @param description
- */
- public Movie(String title, String description) {
- this.title = title;
- this.description = description;
- }
-
- public String getTitle() {
- return title;
- }
-
- public List getActors() {
- return actors;
- }
-
- public void setActors(List actors) {
- this.actors = actors;
- }
-
- public String getDescription() {
- return description;
- }
-
- public List getDirectors() {
- return directors;
- }
-
- public void setDirectorss(List directors) {
- this.directors = directors;
- }
-
- public Integer getReleased() {
- return released;
- }
-
- public void setReleased(Integer released) {
- this.released = released;
- }
-}
diff --git a/examples/integrations/neo4j/neo4j-mp/src/main/java/io/helidon/examples/integrations/neo4j/mp/domain/MovieRepository.java b/examples/integrations/neo4j/neo4j-mp/src/main/java/io/helidon/examples/integrations/neo4j/mp/domain/MovieRepository.java
deleted file mode 100644
index c9eb52cef70..00000000000
--- a/examples/integrations/neo4j/neo4j-mp/src/main/java/io/helidon/examples/integrations/neo4j/mp/domain/MovieRepository.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2002-2020 "Neo4j,"
- * Neo4j Sweden AB [http://neo4j.com]
- * This file is part of Neo4j.
- * 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.examples.integrations.neo4j.mp.domain;
-
-import java.util.List;
-
-import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.inject.Inject;
-import org.neo4j.driver.Driver;
-import org.neo4j.driver.Value;
-
-/*
- * Helidon changes are under the copyright of:
- *
- * Copyright (c) 2021, 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.
- *
- */
-
-/**
- * The Movies repository.
- *
- * @author Michael Simons
- */
-@ApplicationScoped
-public class MovieRepository {
-
- private final Driver driver;
-
- /**
- * Constructor.
- * @param driver
- */
- @Inject
- public MovieRepository(Driver driver) {
- this.driver = driver;
- }
-
- /**
- * Return al Movies.
- * @return list with movies
- */
- public List findAll() {
-
- try (var session = driver.session()) {
-
- var query = ""
- + "match (m:Movie) "
- + "match (m) <- [:DIRECTED] - (d:Person) "
- + "match (m) <- [r:ACTED_IN] - (a:Person) "
- + "return m, collect(d) as directors, collect({name:a.name, roles: r.roles}) as actors";
-
- return session.readTransaction(tx -> tx.run(query).list(r -> {
- var movieNode = r.get("m").asNode();
-
- var directors = r.get("directors").asList(v -> {
- var personNode = v.asNode();
- return new Person(personNode.get("born").asInt(), personNode.get("name").asString());
- });
-
- var actors = r.get("actors").asList(v -> {
- return new Actor(v.get("name").asString(), v.get("roles").asList(Value::asString));
- });
-
- var m = new Movie(movieNode.get("title").asString(), movieNode.get("tagline").asString());
- m.setReleased(movieNode.get("released").asInt());
- m.setDirectorss(directors);
- m.setActors(actors);
- return m;
- }));
- }
- }
-}
diff --git a/examples/integrations/neo4j/neo4j-mp/src/main/java/io/helidon/examples/integrations/neo4j/mp/domain/Person.java b/examples/integrations/neo4j/neo4j-mp/src/main/java/io/helidon/examples/integrations/neo4j/mp/domain/Person.java
deleted file mode 100644
index 692a58e7e93..00000000000
--- a/examples/integrations/neo4j/neo4j-mp/src/main/java/io/helidon/examples/integrations/neo4j/mp/domain/Person.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2002-2020 "Neo4j,"
- * Neo4j Sweden AB [http://neo4j.com]
- * This file is part of Neo4j.
- * 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.examples.integrations.neo4j.mp.domain;
-
-/*
- * Helidon changes are under the copyright of:
- *
- * Copyright (c) 2021, 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.
- *
- */
-
-/**
- * The Person class.
- *
- * @author Michael Simons
- */
-public class Person {
-
- private final String name;
-
- private Integer born;
-
- /**
- * Person constructor.
- *
- * @param born
- * @param name
- */
- public Person(Integer born, String name) {
- this.born = born;
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- public Integer getBorn() {
- return born;
- }
-
- public void setBorn(Integer born) {
- this.born = born;
- }
-
- @SuppressWarnings("checkstyle:OperatorWrap")
- @Override
- public String toString() {
- return "Person{" +
- "name='" + name + '\'' +
- ", born=" + born +
- '}';
- }
-}
diff --git a/examples/integrations/neo4j/neo4j-mp/src/main/java/io/helidon/examples/integrations/neo4j/mp/domain/package-info.java b/examples/integrations/neo4j/neo4j-mp/src/main/java/io/helidon/examples/integrations/neo4j/mp/domain/package-info.java
deleted file mode 100644
index 0883266ea9e..00000000000
--- a/examples/integrations/neo4j/neo4j-mp/src/main/java/io/helidon/examples/integrations/neo4j/mp/domain/package-info.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2021 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.
- */
-/**
- * Domain objects for movie DB.
- */
-package io.helidon.examples.integrations.neo4j.mp.domain;
diff --git a/examples/integrations/neo4j/neo4j-mp/src/main/resources/META-INF/beans.xml b/examples/integrations/neo4j/neo4j-mp/src/main/resources/META-INF/beans.xml
deleted file mode 100644
index dbf3e648c1e..00000000000
--- a/examples/integrations/neo4j/neo4j-mp/src/main/resources/META-INF/beans.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
diff --git a/examples/integrations/neo4j/neo4j-mp/src/main/resources/META-INF/microprofile-config.properties b/examples/integrations/neo4j/neo4j-mp/src/main/resources/META-INF/microprofile-config.properties
deleted file mode 100644
index 70f63d64091..00000000000
--- a/examples/integrations/neo4j/neo4j-mp/src/main/resources/META-INF/microprofile-config.properties
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Copyright (c) 2021 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.
-#
-
-# Application properties. This is the default greeting
-app.greeting=Hello
-
-# Microprofile server properties
-server.port=8080
-server.host=0.0.0.0
-
-# Enable the optional MicroProfile Metrics REST.request metrics
-metrics.rest-request.enabled=true
-
-# Neo4j settings
-neo4j.uri=bolt://localhost:7687
-neo4j.authentication.username=neo4j
-neo4j.authentication.password: secret
-neo4j.pool.metricsEnabled: true
diff --git a/examples/integrations/neo4j/neo4j-mp/src/main/resources/logging.properties b/examples/integrations/neo4j/neo4j-mp/src/main/resources/logging.properties
deleted file mode 100644
index b3e1f27ca75..00000000000
--- a/examples/integrations/neo4j/neo4j-mp/src/main/resources/logging.properties
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (c) 2021, 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.
-#
-
-# Example Logging Configuration File
-# For more information see $JAVA_HOME/jre/lib/logging.properties
-
-# Send messages to the console
-handlers=io.helidon.logging.jul.HelidonConsoleHandler
-
-# HelidonConsoleHandler uses a SimpleFormatter subclass that replaces "!thread!" with the current thread
-java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$s %3$s !thread!: %5$s%6$s%n
-
-# Global logging level. Can be overridden by specific loggers
-.level=INFO
diff --git a/examples/integrations/neo4j/neo4j-mp/src/test/java/io/helidon/examples/integrations/neo4j/mp/MainTest.java b/examples/integrations/neo4j/neo4j-mp/src/test/java/io/helidon/examples/integrations/neo4j/mp/MainTest.java
deleted file mode 100644
index 60f39e02d4c..00000000000
--- a/examples/integrations/neo4j/neo4j-mp/src/test/java/io/helidon/examples/integrations/neo4j/mp/MainTest.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2021, 2023 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.examples.integrations.neo4j.mp;
-
-import io.helidon.microprofile.server.Server;
-
-import jakarta.enterprise.inject.se.SeContainer;
-import jakarta.enterprise.inject.spi.CDI;
-import jakarta.json.JsonArray;
-import jakarta.json.JsonObject;
-import jakarta.ws.rs.client.Client;
-import jakarta.ws.rs.client.ClientBuilder;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-import org.neo4j.harness.Neo4j;
-import org.neo4j.harness.Neo4jBuilders;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-
-/**
- * Main tests of the application done here.
- */
-@Disabled("3.0.0-JAKARTA") // OpenAPI
-// Caused by: java.lang.NoSuchMethodError: 'java.util.List org.jboss.jandex.ClassInfo.unsortedFields()'
-class MainTest {
- private static Server server;
- private static Neo4j embeddedDatabaseServer;
-
- @BeforeAll
- public static void startTheServer() throws Exception {
-
- embeddedDatabaseServer = Neo4jBuilders.newInProcessBuilder()
- .withDisabledServer()
- .withFixture(FIXTURE)
- .build();
-
- System.setProperty("neo4j.uri", embeddedDatabaseServer.boltURI().toString());
-
- server = Server.create().start();
-
- }
-
- @AfterAll
- static void destroyClass() {
- CDI
- org.jboss.jandex
+ io.smallryejandex-maven-plugin
diff --git a/examples/integrations/oci/atp-reactive/src/main/java/io/helidon/examples/integrations/oci/atp/reactive/OciAtpMain.java b/examples/integrations/oci/atp-reactive/src/main/java/io/helidon/examples/integrations/oci/atp/reactive/OciAtpMain.java
deleted file mode 100644
index 91057ba8ed0..00000000000
--- a/examples/integrations/oci/atp-reactive/src/main/java/io/helidon/examples/integrations/oci/atp/reactive/OciAtpMain.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2021, 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.examples.integrations.oci.atp.reactive;
-
-import java.io.IOException;
-
-import io.helidon.logging.common.LogConfig;
-import io.helidon.config.Config;
-import io.helidon.reactive.webserver.Routing;
-import io.helidon.reactive.webserver.WebServer;
-
-import com.oracle.bmc.ConfigFileReader;
-import com.oracle.bmc.auth.AuthenticationDetailsProvider;
-import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider;
-import com.oracle.bmc.database.DatabaseAsync;
-import com.oracle.bmc.database.DatabaseAsyncClient;
-import com.oracle.bmc.model.BmcException;
-
-/**
- * Main class of the example.
- * This example sets up a web server to serve REST API to retrieve ATP wallet.
- */
-public final class OciAtpMain {
- /**
- * Cannot be instantiated.
- */
- private OciAtpMain() {
- }
-
- /**
- * Application main entry point.
- *
- * @param args command line arguments.
- */
- public static void main(String[] args) throws IOException {
- // load logging configuration
- LogConfig.configureRuntime();
-
- // By default this will pick up application.yaml from the classpath
- Config config = Config.create();
-
- // this requires OCI configuration in the usual place
- // ~/.oci/config
- AuthenticationDetailsProvider authProvider = new ConfigFileAuthenticationDetailsProvider(ConfigFileReader.parseDefault());
- DatabaseAsync databaseAsyncClient = DatabaseAsyncClient.builder().build(authProvider);
-
- // Prepare routing for the server
- WebServer server = WebServer.builder()
- .config(config.get("server"))
- .routing(Routing.builder()
- .register("/atp", new AtpService(databaseAsyncClient, config))
- // OCI SDK error handling
- .error(BmcException.class, (req, res, ex) -> res.status(ex.getStatusCode())
- .send(ex.getMessage())))
- .build();
-
- // Start the server and print some info.
- server.start().thenAccept(ws -> {
- System.out.println(
- "WEB server is up! http://localhost:" + ws.port() + "/");
- });
-
- // Server threads are not daemon. NO need to block. Just react.
- server.whenShutdown().thenRun(() -> System.out.println("WEB server is DOWN. Good bye!"));
- }
-}
diff --git a/examples/integrations/oci/atp-reactive/src/main/java/io/helidon/examples/integrations/oci/atp/reactive/OciResponseHandler.java b/examples/integrations/oci/atp-reactive/src/main/java/io/helidon/examples/integrations/oci/atp/reactive/OciResponseHandler.java
deleted file mode 100644
index 0eac2a44fa5..00000000000
--- a/examples/integrations/oci/atp-reactive/src/main/java/io/helidon/examples/integrations/oci/atp/reactive/OciResponseHandler.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.examples.integrations.oci.atp.reactive;
-
-import java.util.concurrent.CountDownLatch;
-
-import com.oracle.bmc.responses.AsyncHandler;
-
-final class OciResponseHandler implements AsyncHandler {
- private OUT item;
- private Throwable failed = null;
- private CountDownLatch latch = new CountDownLatch(1);
-
- protected OUT waitForCompletion() throws Exception {
- latch.await();
- if (failed != null) {
- if (failed instanceof Exception) {
- throw (Exception) failed;
- }
- throw (Error) failed;
- }
- return item;
- }
-
- @Override
- public void onSuccess(IN request, OUT response) {
- item = response;
- latch.countDown();
- }
-
- @Override
- public void onError(IN request, Throwable error) {
- failed = error;
- latch.countDown();
- }
-}
diff --git a/examples/integrations/oci/atp-reactive/src/main/java/io/helidon/examples/integrations/oci/atp/reactive/package-info.java b/examples/integrations/oci/atp-reactive/src/main/java/io/helidon/examples/integrations/oci/atp/reactive/package-info.java
deleted file mode 100644
index ee7800316ed..00000000000
--- a/examples/integrations/oci/atp-reactive/src/main/java/io/helidon/examples/integrations/oci/atp/reactive/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2021 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.
- */
-
-/**
- * Example of integration with OCI ATP in reactive application.
- */
-package io.helidon.examples.integrations.oci.atp.reactive;
diff --git a/examples/integrations/oci/atp-reactive/README.md b/examples/integrations/oci/atp/README.md
similarity index 91%
rename from examples/integrations/oci/atp-reactive/README.md
rename to examples/integrations/oci/atp/README.md
index 20b402558c1..bcba8b88a77 100644
--- a/examples/integrations/oci/atp-reactive/README.md
+++ b/examples/integrations/oci/atp/README.md
@@ -1,4 +1,4 @@
-# Helidon ATP Reactive Examples
+# Helidon ATP Nima Examples
This example demonstrates how user can easily retrieve wallet from their ATP instance running in OCI and use information from that wallet to setup DataSource to do Database operations.
@@ -16,7 +16,7 @@ Once you have updated required properties, you can run the example:
```shell script
mvn clean install
-java -jar ./target/helidon-examples-integrations-oci-atp-reactive.jar
+java -jar ./target/helidon-examples-integrations-oci-atp.jar
```
To verify that, you can retrieve wallet and do database operation:
diff --git a/examples/integrations/oci/atp-reactive/pom.xml b/examples/integrations/oci/atp/pom.xml
similarity index 86%
rename from examples/integrations/oci/atp-reactive/pom.xml
rename to examples/integrations/oci/atp/pom.xml
index 90956f5db61..03856861c55 100644
--- a/examples/integrations/oci/atp-reactive/pom.xml
+++ b/examples/integrations/oci/atp/pom.xml
@@ -29,18 +29,18 @@
io.helidon.examples.integrations.oci
- helidon-examples-integrations-oci-atp-reactive
- Helidon Examples Integration OCI ATP Reactive
- Reactive integration with OCI ATP.
+ helidon-examples-integrations-oci-atp
+ Helidon Examples Integration OCI ATP Nima
+ Nima integration with OCI ATP.
- io.helidon.examples.integrations.oci.atp.reactive.OciAtpMain
+ io.helidon.examples.integrations.oci.atp.OciAtpMain
- io.helidon.reactive.webserver
- helidon-reactive-webserver
+ io.helidon.nima.webserver
+ helidon-nima-webserverio.helidon.reactive.dbclient
diff --git a/examples/integrations/oci/atp-reactive/src/main/java/io/helidon/examples/integrations/oci/atp/reactive/AtpService.java b/examples/integrations/oci/atp/src/main/java/io/helidon/examples/integrations/oci/atp/AtpService.java
similarity index 65%
rename from examples/integrations/oci/atp-reactive/src/main/java/io/helidon/examples/integrations/oci/atp/reactive/AtpService.java
rename to examples/integrations/oci/atp/src/main/java/io/helidon/examples/integrations/oci/atp/AtpService.java
index 9e0243c0cdc..fc2ce73e623 100644
--- a/examples/integrations/oci/atp-reactive/src/main/java/io/helidon/examples/integrations/oci/atp/reactive/AtpService.java
+++ b/examples/integrations/oci/atp/src/main/java/io/helidon/examples/integrations/oci/atp/AtpService.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2021, 2023 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package io.helidon.examples.integrations.oci.atp.reactive;
+package io.helidon.examples.integrations.oci.atp;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
@@ -22,6 +22,7 @@
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.sql.SQLException;
+import java.time.Duration;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
@@ -32,16 +33,19 @@
import javax.net.ssl.TrustManagerFactory;
import io.helidon.common.http.Http;
-import io.helidon.common.reactive.Single;
import io.helidon.config.Config;
+import io.helidon.config.ConfigException;
+import io.helidon.nima.webserver.http.HttpRules;
+import io.helidon.nima.webserver.http.HttpService;
+import io.helidon.nima.webserver.http.ServerRequest;
+import io.helidon.nima.webserver.http.ServerResponse;
import io.helidon.reactive.dbclient.DbClient;
import io.helidon.reactive.dbclient.jdbc.JdbcDbClientProvider;
-import io.helidon.reactive.webserver.Routing;
-import io.helidon.reactive.webserver.ServerRequest;
-import io.helidon.reactive.webserver.ServerResponse;
-import io.helidon.reactive.webserver.Service;
-import com.oracle.bmc.database.DatabaseAsync;
+import com.oracle.bmc.ConfigFileReader;
+import com.oracle.bmc.auth.AuthenticationDetailsProvider;
+import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider;
+import com.oracle.bmc.database.DatabaseClient;
import com.oracle.bmc.database.model.GenerateAutonomousDatabaseWalletDetails;
import com.oracle.bmc.database.requests.GenerateAutonomousDatabaseWalletRequest;
import com.oracle.bmc.database.responses.GenerateAutonomousDatabaseWalletResponse;
@@ -50,45 +54,48 @@
import oracle.ucp.jdbc.PoolDataSource;
import oracle.ucp.jdbc.PoolDataSourceFactory;
-class AtpService implements Service {
+class AtpService implements HttpService {
private static final Logger LOGGER = Logger.getLogger(AtpService.class.getName());
- private final DatabaseAsync databaseAsyncClient;
+ private final DatabaseClient databaseClient;
private final Config config;
- AtpService(DatabaseAsync databaseAsyncClient, Config config) {
- this.databaseAsyncClient = databaseAsyncClient;
- this.config = config;
+ AtpService(Config config) {
+ try {
+ // this requires OCI configuration in the usual place
+ // ~/.oci/config
+ AuthenticationDetailsProvider authProvider = new ConfigFileAuthenticationDetailsProvider(ConfigFileReader.parseDefault());
+ databaseClient = DatabaseClient.builder().build(authProvider);
+ this.config = config;
+ } catch (IOException e) {
+ throw new ConfigException("Failed to read configuration properties", e);
+ }
}
- @Override
- public void update(Routing.Rules rules) {
+ /**
+ * A service registers itself by updating the routine rules.
+ *
+ * @param rules the routing rules.
+ */
+ public void routing(HttpRules rules) {
rules.get("/wallet", this::generateWallet);
}
/**
* Generate wallet file for the configured ATP.
+ *
+ * @param req request
+ * @param res response
*/
private void generateWallet(ServerRequest req, ServerResponse res) {
- OciResponseHandler walletHandler =
- new OciResponseHandler<>();
- GenerateAutonomousDatabaseWalletResponse walletResponse = null;
- try {
- databaseAsyncClient.generateAutonomousDatabaseWallet(
- GenerateAutonomousDatabaseWalletRequest.builder()
- .autonomousDatabaseId(config.get("oci.atp.ocid").asString().get())
- .generateAutonomousDatabaseWalletDetails(
- GenerateAutonomousDatabaseWalletDetails.builder()
- .password(config.get("oci.atp.walletPassword").asString().get())
- .build())
- .build(), walletHandler);
- walletResponse = walletHandler.waitForCompletion();
- } catch (Exception e) {
- LOGGER.log(Level.SEVERE, "Error waiting for GenerateAutonomousDatabaseWalletResponse", e);
- res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send();
- return;
- }
+ GenerateAutonomousDatabaseWalletResponse walletResponse = databaseClient.generateAutonomousDatabaseWallet(
+ GenerateAutonomousDatabaseWalletRequest.builder()
+ .autonomousDatabaseId(config.get("oci.atp.ocid").asString().get())
+ .generateAutonomousDatabaseWalletDetails(
+ GenerateAutonomousDatabaseWalletDetails.builder()
+ .password(config.get("oci.atp.walletPassword").asString().get())
+ .build())
+ .build());
if (walletResponse.getContentLength() == 0) {
LOGGER.log(Level.SEVERE, "GenerateAutonomousDatabaseWalletResponse is empty");
@@ -101,20 +108,27 @@ private void generateWallet(ServerRequest req, ServerResponse res) {
walletContent = walletResponse.getInputStream().readAllBytes();
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Error processing GenerateAutonomousDatabaseWalletResponse", e);
- res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send();
+ res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send(e.getMessage());
return;
}
- createDbClient(walletContent)
- .flatMap(dbClient -> dbClient.execute(exec -> exec.query("SELECT 'Hello world!!' FROM DUAL")))
- .first()
- .map(dbRow -> dbRow.column(1).as(String.class))
- .ifEmpty(() -> res.status(404).send())
- .onError(res::send)
- .forSingle(res::send);
+ try {
+ String result = createDbClient(walletContent)
+ .execute(exec -> exec.query("SELECT 'Hello world!!' FROM DUAL"))
+ .first()
+ .map(dbRow -> dbRow.column(1).as(String.class))
+ .await(Duration.ofSeconds(60));
+ if (result == null || result.isEmpty()) {
+ res.status(Http.Status.NOT_FOUND_404).send();
+ } else {
+ res.send(result);
+ }
+ } catch (Exception e) {
+ res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send(e.getMessage());
+ }
}
- Single createDbClient(byte[] walletContent) {
+ DbClient createDbClient(byte[] walletContent) {
PoolDataSource pds = PoolDataSourceFactory.getPoolDataSource();
try {
pds.setSSLContext(getSSLContext(walletContent));
@@ -123,22 +137,23 @@ Single createDbClient(byte[] walletContent) {
.orElseThrow(() -> new IllegalStateException("Missing tnsNetServiceName!!"))));
pds.setUser(config.get("db.userName").as(String.class).orElse("ADMIN"));
pds.setPassword(config.get("db.password")
- .as(String.class)
- .orElseThrow(() -> new IllegalStateException("Missing password!!")));
+ .as(String.class)
+ .orElseThrow(() -> new IllegalStateException("Missing password!!")));
pds.setConnectionFactoryClassName(OracleDataSource.class.getName());
} catch (SQLException e) {
LOGGER.log(Level.SEVERE, "Error setting up PoolDataSource", e);
- return Single.error(e);
+ throw new RuntimeException(e);
}
- return Single.just(new JdbcDbClientProvider().builder()
- .connectionPool(() -> {
- try {
- return pds.getConnection();
- } catch (SQLException e) {
- throw new IllegalStateException("Error while setting up new connection", e);
- }
- })
- .build());
+
+ return new JdbcDbClientProvider().builder()
+ .connectionPool(() -> {
+ try {
+ return pds.getConnection();
+ } catch (SQLException e) {
+ throw new IllegalStateException("Error while setting up new connection", e);
+ }
+ })
+ .build();
}
/**
@@ -174,8 +189,8 @@ private static SSLContext getSSLContext(byte[] walletContent) throws IllegalStat
/**
* Returns JDBC URL with connection description for the given service based on tnsnames.ora in wallet.
*
- * @param walletContent
- * @param tnsNetServiceName
+ * @param walletContent walletContent
+ * @param tnsNetServiceName tnsNetServiceName
* @return String
*/
private static String getJdbcUrl(byte[] walletContent, String tnsNetServiceName) throws IllegalStateException {
diff --git a/examples/integrations/oci/atp/src/main/java/io/helidon/examples/integrations/oci/atp/OciAtpMain.java b/examples/integrations/oci/atp/src/main/java/io/helidon/examples/integrations/oci/atp/OciAtpMain.java
new file mode 100644
index 00000000000..e63672babe9
--- /dev/null
+++ b/examples/integrations/oci/atp/src/main/java/io/helidon/examples/integrations/oci/atp/OciAtpMain.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2021, 2023 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.examples.integrations.oci.atp;
+
+import java.io.IOException;
+
+import io.helidon.config.Config;
+import io.helidon.logging.common.LogConfig;
+import io.helidon.nima.webserver.WebServer;
+import io.helidon.nima.webserver.http.HttpRouting;
+
+/**
+ * Main class of the example.
+ * This example sets up a web server to serve REST API to retrieve ATP wallet.
+ */
+public final class OciAtpMain {
+
+ private static Config config;
+
+ /**
+ * Cannot be instantiated.
+ */
+ private OciAtpMain() {
+ }
+
+ /**
+ * Application main entry point.
+ *
+ * @param args command line arguments.
+ */
+ public static void main(String[] args) throws IOException {
+ // load logging configuration
+ LogConfig.configureRuntime();
+
+ // By default this will pick up application.yaml from the classpath
+ config = Config.create();
+
+ WebServer server = WebServer.builder()
+ .routing(OciAtpMain::routing)
+ .config(config.get("server"))
+ .start();
+
+ System.out.println("WEB server is up! http://localhost:" + server.port());
+ }
+
+ /**
+ * Updates HTTP Routing.
+ */
+ static void routing(HttpRouting.Builder routing) {
+ AtpService atpService = new AtpService(config);
+ routing.register("/atp", atpService);
+ }
+}
diff --git a/examples/integrations/oci/atp/src/main/java/io/helidon/examples/integrations/oci/atp/package-info.java b/examples/integrations/oci/atp/src/main/java/io/helidon/examples/integrations/oci/atp/package-info.java
new file mode 100644
index 00000000000..35e3363181b
--- /dev/null
+++ b/examples/integrations/oci/atp/src/main/java/io/helidon/examples/integrations/oci/atp/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021, 2023 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.
+ */
+
+/**
+ * Example of integration with OCI ATP in Nima application.
+ */
+package io.helidon.examples.integrations.oci.atp;
diff --git a/examples/integrations/oci/atp-reactive/src/main/resources/application.yaml b/examples/integrations/oci/atp/src/main/resources/application.yaml
similarity index 94%
rename from examples/integrations/oci/atp-reactive/src/main/resources/application.yaml
rename to examples/integrations/oci/atp/src/main/resources/application.yaml
index 156f26ed159..b65d90eccd2 100644
--- a/examples/integrations/oci/atp-reactive/src/main/resources/application.yaml
+++ b/examples/integrations/oci/atp/src/main/resources/application.yaml
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2021, 2022 Oracle and/or its affiliates.
+# Copyright (c) 2021, 2023 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.
diff --git a/examples/integrations/oci/objectstorage-reactive/src/main/resources/logging.properties b/examples/integrations/oci/atp/src/main/resources/logging.properties
similarity index 94%
rename from examples/integrations/oci/objectstorage-reactive/src/main/resources/logging.properties
rename to examples/integrations/oci/atp/src/main/resources/logging.properties
index 43cd0f29d7d..c09e76d612c 100644
--- a/examples/integrations/oci/objectstorage-reactive/src/main/resources/logging.properties
+++ b/examples/integrations/oci/atp/src/main/resources/logging.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2021, 2022 Oracle and/or its affiliates.
+# Copyright (c) 2021, 2023 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.
diff --git a/examples/integrations/oci/metrics-reactive/pom.xml b/examples/integrations/oci/metrics/pom.xml
similarity index 84%
rename from examples/integrations/oci/metrics-reactive/pom.xml
rename to examples/integrations/oci/metrics/pom.xml
index 84d18bb3c70..0acc6710b1a 100644
--- a/examples/integrations/oci/metrics-reactive/pom.xml
+++ b/examples/integrations/oci/metrics/pom.xml
@@ -29,19 +29,15 @@
- io.helidon.examples.integrations.oci.telemetry.reactive.OciMetricsMain
+ io.helidon.examples.integrations.oci.telemetry.OciMetricsMainio.helidon.examples.integrations.oci
- helidon-examples-integrations-oci-metrics-reactive
- Helidon Examples Integration OCI Metrics Reactive
- Reactive integration with OCI Metrics.
+ helidon-examples-integrations-oci-metrics
+ Helidon Examples Integration OCI Metrics
+ Integration with OCI Metrics.
-
- io.helidon.reactive.webserver
- helidon-reactive-webserver
- io.helidon.confighelidon-config-yaml
diff --git a/examples/integrations/oci/metrics-reactive/src/main/java/io/helidon/examples/integrations/oci/telemetry/reactive/OciMetricsMain.java b/examples/integrations/oci/metrics/src/main/java/io/helidon/examples/integrations/oci/telemetry/OciMetricsMain.java
similarity index 61%
rename from examples/integrations/oci/metrics-reactive/src/main/java/io/helidon/examples/integrations/oci/telemetry/reactive/OciMetricsMain.java
rename to examples/integrations/oci/metrics/src/main/java/io/helidon/examples/integrations/oci/telemetry/OciMetricsMain.java
index a7073137da8..77e0ee9282c 100644
--- a/examples/integrations/oci/metrics-reactive/src/main/java/io/helidon/examples/integrations/oci/telemetry/reactive/OciMetricsMain.java
+++ b/examples/integrations/oci/metrics/src/main/java/io/helidon/examples/integrations/oci/telemetry/OciMetricsMain.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2021, 2023 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package io.helidon.examples.integrations.oci.telemetry.reactive;
+package io.helidon.examples.integrations.oci.telemetry;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
@@ -22,24 +22,18 @@
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
-import java.util.concurrent.CountDownLatch;
-import io.helidon.logging.common.LogConfig;
import io.helidon.config.Config;
+import io.helidon.logging.common.LogConfig;
import com.oracle.bmc.ConfigFileReader;
import com.oracle.bmc.auth.AuthenticationDetailsProvider;
import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider;
-import com.oracle.bmc.monitoring.MonitoringAsync;
-import com.oracle.bmc.monitoring.MonitoringAsyncClient;
-import com.oracle.bmc.monitoring.model.Datapoint;
-import com.oracle.bmc.monitoring.model.FailedMetricRecord;
-import com.oracle.bmc.monitoring.model.MetricDataDetails;
-import com.oracle.bmc.monitoring.model.PostMetricDataDetails;
-import com.oracle.bmc.monitoring.model.PostMetricDataResponseDetails;
+import com.oracle.bmc.monitoring.Monitoring;
+import com.oracle.bmc.monitoring.MonitoringClient;
+import com.oracle.bmc.monitoring.model.*;
import com.oracle.bmc.monitoring.requests.PostMetricDataRequest;
import com.oracle.bmc.monitoring.responses.PostMetricDataResponse;
-import com.oracle.bmc.responses.AsyncHandler;
import static io.helidon.config.ConfigSources.classpath;
import static io.helidon.config.ConfigSources.file;
@@ -54,6 +48,7 @@ private OciMetricsMain() {
/**
* Main method.
+ *
* @param args ignored
*/
public static void main(String[] args) throws Exception {
@@ -67,29 +62,23 @@ public static void main(String[] args) throws Exception {
// this requires OCI configuration in the usual place
// ~/.oci/config
AuthenticationDetailsProvider authProvider = new ConfigFileAuthenticationDetailsProvider(ConfigFileReader.parseDefault());
- MonitoringAsync monitoringAsyncClient = new MonitoringAsyncClient(authProvider);
- monitoringAsyncClient.setEndpoint(monitoringAsyncClient.getEndpoint().replace("telemetry.", "telemetry-ingestion."));
-
- PostMetricDataRequest postMetricDataRequest = PostMetricDataRequest.builder()
- .postMetricDataDetails(getPostMetricDataDetails(config))
- .build();
- /*
- * Invoke the API call. I use .await() to block the call, as otherwise our
- * main method would finish without waiting for the response.
- * In a real reactive application, this should not be done (as you would write the response
- * to a server response or use other reactive/non-blocking APIs).
- */
- ResponseHandler monitoringHandler =
- new ResponseHandler<>();
- monitoringAsyncClient.postMetricData(postMetricDataRequest, monitoringHandler);
- PostMetricDataResponse postMetricDataResponse = monitoringHandler.waitForCompletion();
- PostMetricDataResponseDetails postMetricDataResponseDetails = postMetricDataResponse.getPostMetricDataResponseDetails();
- int count = postMetricDataResponseDetails.getFailedMetricsCount();
- System.out.println("Failed count: " + count);
- if (count > 0) {
- System.out.println("Failed metrics:");
- for (FailedMetricRecord failedMetric : postMetricDataResponseDetails.getFailedMetrics()) {
- System.out.println("\t" + failedMetric.getMessage() + ": " + failedMetric.getMetricData());
+ try (Monitoring monitoringClient = MonitoringClient.builder().build(authProvider)) {
+ monitoringClient.setEndpoint(monitoringClient.getEndpoint().replace("telemetry.", "telemetry-ingestion."));
+
+ PostMetricDataRequest postMetricDataRequest = PostMetricDataRequest.builder()
+ .postMetricDataDetails(getPostMetricDataDetails(config))
+ .build();
+
+ // Invoke the API call.
+ PostMetricDataResponse postMetricDataResponse = monitoringClient.postMetricData(postMetricDataRequest);
+ PostMetricDataResponseDetails postMetricDataResponseDetails = postMetricDataResponse.getPostMetricDataResponseDetails();
+ int count = postMetricDataResponseDetails.getFailedMetricsCount();
+ System.out.println("Failed count: " + count);
+ if (count > 0) {
+ System.out.println("Failed metrics:");
+ for (FailedMetricRecord failedMetric : postMetricDataResponseDetails.getFailedMetrics()) {
+ System.out.println("\t" + failedMetric.getMessage() + ": " + failedMetric.getMetricData());
+ }
}
}
}
@@ -143,33 +132,4 @@ private static Map makeMap(String... data) {
}
return map;
}
-
- private static class ResponseHandler implements AsyncHandler {
- private OUT item;
- private Throwable failed = null;
- private CountDownLatch latch = new CountDownLatch(1);
-
- private OUT waitForCompletion() throws Exception {
- latch.await();
- if (failed != null) {
- if (failed instanceof Exception) {
- throw (Exception) failed;
- }
- throw (Error) failed;
- }
- return item;
- }
-
- @Override
- public void onSuccess(IN request, OUT response) {
- item = response;
- latch.countDown();
- }
-
- @Override
- public void onError(IN request, Throwable error) {
- failed = error;
- latch.countDown();
- }
- }
}
diff --git a/examples/integrations/oci/metrics/src/main/java/io/helidon/examples/integrations/oci/telemetry/package-info.java b/examples/integrations/oci/metrics/src/main/java/io/helidon/examples/integrations/oci/telemetry/package-info.java
new file mode 100644
index 00000000000..3fc15dd7d8a
--- /dev/null
+++ b/examples/integrations/oci/metrics/src/main/java/io/helidon/examples/integrations/oci/telemetry/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021, 2023 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.
+ */
+
+/**
+ * Example using OCI metrics blocking API.
+ */
+package io.helidon.examples.integrations.oci.telemetry;
diff --git a/examples/integrations/oci/metrics-reactive/src/main/resources/application.yaml b/examples/integrations/oci/metrics/src/main/resources/application.yaml
similarity index 92%
rename from examples/integrations/oci/metrics-reactive/src/main/resources/application.yaml
rename to examples/integrations/oci/metrics/src/main/resources/application.yaml
index d9304c7641e..c2c669e26ca 100644
--- a/examples/integrations/oci/metrics-reactive/src/main/resources/application.yaml
+++ b/examples/integrations/oci/metrics/src/main/resources/application.yaml
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2021 Oracle and/or its affiliates.
+# Copyright (c) 2021, 2023 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.
diff --git a/examples/integrations/oci/vault-reactive/src/main/resources/logging.properties b/examples/integrations/oci/metrics/src/main/resources/logging.properties
similarity index 94%
rename from examples/integrations/oci/vault-reactive/src/main/resources/logging.properties
rename to examples/integrations/oci/metrics/src/main/resources/logging.properties
index f8802f90626..341cef8ce9e 100644
--- a/examples/integrations/oci/vault-reactive/src/main/resources/logging.properties
+++ b/examples/integrations/oci/metrics/src/main/resources/logging.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2021, 2022 Oracle and/or its affiliates.
+# Copyright (c) 2021, 2023 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.
diff --git a/examples/integrations/oci/objectstorage-cdi/pom.xml b/examples/integrations/oci/objectstorage-cdi/pom.xml
index fbe0121e50c..cd80c3664ac 100644
--- a/examples/integrations/oci/objectstorage-cdi/pom.xml
+++ b/examples/integrations/oci/objectstorage-cdi/pom.xml
@@ -55,7 +55,7 @@
helidon-config-yaml-mp
- org.jboss
+ io.smallryejandexruntime
@@ -73,7 +73,7 @@
- org.jboss.jandex
+ io.smallryejandex-maven-plugin
diff --git a/examples/integrations/oci/objectstorage-reactive/src/main/java/io/helidon/examples/integrations/oci/objecstorage/reactive/ObjectStorageService.java b/examples/integrations/oci/objectstorage-reactive/src/main/java/io/helidon/examples/integrations/oci/objecstorage/reactive/ObjectStorageService.java
deleted file mode 100644
index c4cbbe25694..00000000000
--- a/examples/integrations/oci/objectstorage-reactive/src/main/java/io/helidon/examples/integrations/oci/objecstorage/reactive/ObjectStorageService.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (c) 2021, 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.examples.integrations.oci.objecstorage.reactive;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.concurrent.CountDownLatch;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import io.helidon.common.http.Http;
-import io.helidon.reactive.webserver.Routing;
-import io.helidon.reactive.webserver.ServerRequest;
-import io.helidon.reactive.webserver.ServerResponse;
-import io.helidon.reactive.webserver.Service;
-
-import com.oracle.bmc.objectstorage.ObjectStorageAsync;
-import com.oracle.bmc.objectstorage.model.RenameObjectDetails;
-import com.oracle.bmc.objectstorage.requests.DeleteObjectRequest;
-import com.oracle.bmc.objectstorage.requests.GetNamespaceRequest;
-import com.oracle.bmc.objectstorage.requests.GetObjectRequest;
-import com.oracle.bmc.objectstorage.requests.PutObjectRequest;
-import com.oracle.bmc.objectstorage.requests.RenameObjectRequest;
-import com.oracle.bmc.objectstorage.responses.DeleteObjectResponse;
-import com.oracle.bmc.objectstorage.responses.GetNamespaceResponse;
-import com.oracle.bmc.objectstorage.responses.GetObjectResponse;
-import com.oracle.bmc.objectstorage.responses.PutObjectResponse;
-import com.oracle.bmc.objectstorage.responses.RenameObjectResponse;
-import com.oracle.bmc.responses.AsyncHandler;
-
-class ObjectStorageService implements Service {
- private static final Logger LOGGER = Logger.getLogger(ObjectStorageService.class.getName());
- private final ObjectStorageAsync objectStorageAsyncClient;
- private final String bucketName;
- private final String namespaceName;
-
- ObjectStorageService(ObjectStorageAsync objectStorageAsyncClient, String bucketName) throws Exception {
- this.objectStorageAsyncClient = objectStorageAsyncClient;
- this.bucketName = bucketName;
- ResponseHandler namespaceHandler =
- new ResponseHandler<>();
- this.objectStorageAsyncClient.getNamespace(GetNamespaceRequest.builder().build(), namespaceHandler);
- GetNamespaceResponse namespaceResponse = namespaceHandler.waitForCompletion();
- this.namespaceName = namespaceResponse.getValue();
- }
-
- @Override
- public void update(Routing.Rules rules) {
- rules.get("/file/{file-name}", this::download)
- .post("/file/{file-name}", this::upload)
- .delete("/file/{file-name}", this::delete)
- .get("/rename/{old-name}/{new-name}", this::rename);
- }
-
- private void delete(ServerRequest req, ServerResponse res) {
- String objectName = req.path().param("file-name");
-
- ResponseHandler deleteObjectHandler =
- new ResponseHandler<>();
-
- objectStorageAsyncClient.deleteObject(DeleteObjectRequest.builder()
- .namespaceName(namespaceName)
- .bucketName(bucketName)
- .objectName(objectName).build(), deleteObjectHandler);
- try {
- DeleteObjectResponse deleteObjectResponse = deleteObjectHandler.waitForCompletion();
- res.status(Http.Status.OK_200)
- .send();
- return;
- } catch (Exception e) {
- LOGGER.log(Level.SEVERE, "Error deleting object", e);
- res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send();
- return;
- }
- }
-
- private void rename(ServerRequest req, ServerResponse res) {
- String oldName = req.path().param("old-name");
- String newName = req.path().param("new-name");
-
- RenameObjectRequest renameObjectRequest = RenameObjectRequest.builder()
- .namespaceName(namespaceName)
- .bucketName(bucketName)
- .renameObjectDetails(RenameObjectDetails.builder()
- .newName(newName)
- .sourceName(oldName)
- .build())
- .build();
-
- ResponseHandler renameObjectHandler =
- new ResponseHandler<>();
-
- try {
- objectStorageAsyncClient.renameObject(renameObjectRequest, renameObjectHandler);
- RenameObjectResponse renameObjectResponse = renameObjectHandler.waitForCompletion();
- res.status(Http.Status.OK_200)
- .send();
- return;
- } catch (Exception e) {
- LOGGER.log(Level.SEVERE, "Error renaming object", e);
- res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send();
- return;
- }
- }
-
- private void upload(ServerRequest req, ServerResponse res) {
- String objectName = req.path().param("file-name");
- PutObjectRequest putObjectRequest = null;
- try (InputStream stream = new FileInputStream(System.getProperty("user.dir") + File.separator + objectName)) {
- byte[] contents = stream.readAllBytes();
- putObjectRequest =
- PutObjectRequest.builder()
- .namespaceName(namespaceName)
- .bucketName(bucketName)
- .objectName(objectName)
- .putObjectBody(new ByteArrayInputStream(contents))
- .contentLength(Long.valueOf(contents.length))
- .build();
- } catch (Exception e) {
- LOGGER.log(Level.SEVERE, "Error creating PutObjectRequest", e);
- res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send();
- return;
- }
-
- ResponseHandler putObjectHandler =
- new ResponseHandler<>();
-
- try {
- objectStorageAsyncClient.putObject(putObjectRequest, putObjectHandler);
- PutObjectResponse putObjectResponse = putObjectHandler.waitForCompletion();
- res.status(Http.Status.OK_200).send();
- return;
- } catch (Exception e) {
- LOGGER.log(Level.SEVERE, "Error uploading object", e);
- res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send();
- return;
- }
- }
-
- private void download(ServerRequest req, ServerResponse res) {
- String objectName = req.path().param("file-name");
- ResponseHandler objectHandler =
- new ResponseHandler<>();
- GetObjectRequest getObjectRequest =
- GetObjectRequest.builder()
- .namespaceName(namespaceName)
- .bucketName(bucketName)
- .objectName(objectName)
- .build();
- GetObjectResponse getObjectResponse = null;
- try {
- objectStorageAsyncClient.getObject(getObjectRequest, objectHandler);
- getObjectResponse = objectHandler.waitForCompletion();
- } catch (Exception e) {
- LOGGER.log(Level.SEVERE, "Error getting object", e);
- res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send();
- return;
- }
-
- if (getObjectResponse.getContentLength() == 0) {
- LOGGER.log(Level.SEVERE, "GetObjectResponse is empty");
- res.status(Http.Status.NOT_FOUND_404).send();
- return;
- }
-
- try (InputStream fileStream = getObjectResponse.getInputStream()) {
- byte[] objectContent = fileStream.readAllBytes();
- res.addHeader(Http.Header.CONTENT_DISPOSITION, "attachment; filename=\"" + objectName + "\"")
- .status(Http.Status.OK_200).send(objectContent);
- return;
- } catch (IOException e) {
- LOGGER.log(Level.SEVERE, "Error processing GetObjectResponse", e);
- res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send();
- return;
- }
- }
-
- private static class ResponseHandler implements AsyncHandler {
- private OUT item;
- private Throwable failed = null;
- private CountDownLatch latch = new CountDownLatch(1);
-
- private OUT waitForCompletion() throws Exception {
- latch.await();
- if (failed != null) {
- if (failed instanceof Exception) {
- throw (Exception) failed;
- }
- throw (Error) failed;
- }
- return item;
- }
-
- @Override
- public void onSuccess(IN request, OUT response) {
- item = response;
- latch.countDown();
- }
-
- @Override
- public void onError(IN request, Throwable error) {
- failed = error;
- latch.countDown();
- }
- }
-}
diff --git a/examples/integrations/oci/objectstorage-reactive/src/main/java/io/helidon/examples/integrations/oci/objecstorage/reactive/OciObjectStorageMain.java b/examples/integrations/oci/objectstorage-reactive/src/main/java/io/helidon/examples/integrations/oci/objecstorage/reactive/OciObjectStorageMain.java
deleted file mode 100644
index 4abb8893af3..00000000000
--- a/examples/integrations/oci/objectstorage-reactive/src/main/java/io/helidon/examples/integrations/oci/objecstorage/reactive/OciObjectStorageMain.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2021, 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.examples.integrations.oci.objecstorage.reactive;
-
-import io.helidon.logging.common.LogConfig;
-import io.helidon.config.Config;
-import io.helidon.reactive.webserver.Routing;
-import io.helidon.reactive.webserver.WebServer;
-
-import com.oracle.bmc.ConfigFileReader;
-import com.oracle.bmc.auth.AuthenticationDetailsProvider;
-import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider;
-import com.oracle.bmc.model.BmcException;
-import com.oracle.bmc.objectstorage.ObjectStorageAsync;
-import com.oracle.bmc.objectstorage.ObjectStorageAsyncClient;
-
-import static io.helidon.config.ConfigSources.classpath;
-import static io.helidon.config.ConfigSources.file;
-
-/**
- * Main class of the example.
- * This example sets up a web server to serve REST API to upload/download/delete objects.
- */
-public final class OciObjectStorageMain {
- private OciObjectStorageMain() {
- }
-
- /**
- * Main method.
- *
- * @param args ignored
- */
- public static void main(String[] args) throws Exception {
- LogConfig.configureRuntime();
- // as I cannot share my configuration of OCI, let's combine the configuration
- // from my home directory with the one compiled into the jar
- // when running this example, you can either update the application.yaml in resources directory
- // or use the same approach
- Config config = buildConfig();
-
- Config ociConfig = config.get("oci");
-
- // this requires OCI configuration in the usual place
- // ~/.oci/config
- AuthenticationDetailsProvider authProvider = new ConfigFileAuthenticationDetailsProvider(ConfigFileReader.parseDefault());
- ObjectStorageAsync objectStorageAsyncClient = new ObjectStorageAsyncClient(authProvider);
-
- // the following parameters are required
- String bucketName = ociConfig.get("objectstorage").get("bucketName").asString().get();
-
- WebServer.builder()
- .config(config.get("server"))
- .routing(Routing.builder()
- .register("/files", new ObjectStorageService(objectStorageAsyncClient, bucketName))
- // OCI SDK error handling
- .error(BmcException.class, (req, res, ex) -> res.status(ex.getStatusCode())
- .send(ex.getMessage())))
- .build()
- .start()
- .await();
- }
-
- private static Config buildConfig() {
- return Config.builder()
- .sources(
- // you can use this file to override the defaults that are built-in
- file(System.getProperty("user.home") + "/helidon/conf/examples.yaml").optional(),
- // in jar file (see src/main/resources/application.yaml)
- classpath("application.yaml"))
- .build();
- }
-}
diff --git a/examples/integrations/oci/objectstorage-reactive/src/main/java/io/helidon/examples/integrations/oci/objecstorage/reactive/package-info.java b/examples/integrations/oci/objectstorage-reactive/src/main/java/io/helidon/examples/integrations/oci/objecstorage/reactive/package-info.java
deleted file mode 100644
index 3bda523337e..00000000000
--- a/examples/integrations/oci/objectstorage-reactive/src/main/java/io/helidon/examples/integrations/oci/objecstorage/reactive/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2021 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.
- */
-
-/**
- * Example of integration with OCI object storage in reactive application.
- */
-package io.helidon.examples.integrations.oci.objecstorage.reactive;
diff --git a/examples/integrations/oci/objectstorage-reactive/pom.xml b/examples/integrations/oci/objectstorage/pom.xml
similarity index 85%
rename from examples/integrations/oci/objectstorage-reactive/pom.xml
rename to examples/integrations/oci/objectstorage/pom.xml
index 62cdac5b41c..f7df51ccec8 100644
--- a/examples/integrations/oci/objectstorage-reactive/pom.xml
+++ b/examples/integrations/oci/objectstorage/pom.xml
@@ -29,18 +29,18 @@
io.helidon.examples.integrations.oci
- helidon-examples-integrations-oci-objectstorage-reactive
- Helidon Examples Integration OCI Object Storage Reactive
- Reactive integration with OCI Object Storage.
+ helidon-examples-integrations-oci-objectstorage
+ Helidon Examples Integration OCI Object Storage
+ Nima integration with OCI Object Storage.
- io.helidon.examples.integrations.oci.objecstorage.reactive.OciObjectStorageMain
+ io.helidon.examples.integrations.oci.objecstorage.OciObjectStorageMain
- io.helidon.reactive.webserver
- helidon-reactive-webserver
+ io.helidon.nima.webserver
+ helidon-nima-webserverio.helidon.config
diff --git a/examples/integrations/oci/objectstorage/src/main/java/io/helidon/examples/integrations/oci/objecstorage/ObjectStorageService.java b/examples/integrations/oci/objectstorage/src/main/java/io/helidon/examples/integrations/oci/objecstorage/ObjectStorageService.java
new file mode 100644
index 00000000000..da42cb4e428
--- /dev/null
+++ b/examples/integrations/oci/objectstorage/src/main/java/io/helidon/examples/integrations/oci/objecstorage/ObjectStorageService.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2021, 2023 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.examples.integrations.oci.objecstorage;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import io.helidon.common.http.Http;
+import io.helidon.config.Config;
+import io.helidon.config.ConfigException;
+import io.helidon.nima.webserver.http.HttpRules;
+import io.helidon.nima.webserver.http.HttpService;
+import io.helidon.nima.webserver.http.ServerRequest;
+import io.helidon.nima.webserver.http.ServerResponse;
+
+import com.oracle.bmc.ConfigFileReader;
+import com.oracle.bmc.auth.AuthenticationDetailsProvider;
+import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider;
+import com.oracle.bmc.objectstorage.ObjectStorage;
+import com.oracle.bmc.objectstorage.ObjectStorageClient;
+import com.oracle.bmc.objectstorage.requests.DeleteObjectRequest;
+import com.oracle.bmc.objectstorage.requests.GetNamespaceRequest;
+import com.oracle.bmc.objectstorage.requests.GetObjectRequest;
+import com.oracle.bmc.objectstorage.requests.PutObjectRequest;
+import com.oracle.bmc.objectstorage.responses.DeleteObjectResponse;
+import com.oracle.bmc.objectstorage.responses.GetNamespaceResponse;
+import com.oracle.bmc.objectstorage.responses.GetObjectResponse;
+import com.oracle.bmc.objectstorage.responses.PutObjectResponse;
+
+/**
+ * REST API for the objecstorage example.
+ */
+public class ObjectStorageService implements HttpService {
+ private static final Logger LOGGER = Logger.getLogger(ObjectStorageService.class.getName());
+ private final ObjectStorage objectStorageClient;
+ private final String namespaceName;
+ private final String bucketName;
+
+
+ ObjectStorageService(Config config) {
+ try {
+ AuthenticationDetailsProvider authProvider = new ConfigFileAuthenticationDetailsProvider(ConfigFileReader.parseDefault());
+ this.objectStorageClient = ObjectStorageClient.builder().build(authProvider);
+ this.bucketName = config.get("oci.objectstorage.bucketName")
+ .asString()
+ .orElseThrow(() -> new IllegalStateException("Missing bucket name!!"));
+ GetNamespaceResponse namespaceResponse =
+ this.objectStorageClient.getNamespace(GetNamespaceRequest.builder().build());
+ this.namespaceName = namespaceResponse.getValue();
+ } catch (IOException e) {
+ throw new ConfigException("Failed to read configuration properties", e);
+ }
+ }
+
+ /**
+ * A service registers itself by updating the routine rules.
+ *
+ * @param rules the routing rules.
+ */
+ public void routing(HttpRules rules) {
+ rules.get("/file/{file-name}", this::download);
+ rules.post("/file/{fileName}", this::upload);
+ rules.delete("/file/{file-name}", this::delete);
+ }
+
+ /**
+ * Download a file from object storage.
+ *
+ * @param request request
+ * @param response response
+ */
+ public void download(ServerRequest request, ServerResponse response) {
+ String fileName = request.path().pathParameters().value("file-name");
+ GetObjectResponse getObjectResponse =
+ objectStorageClient.getObject(
+ GetObjectRequest.builder()
+ .namespaceName(namespaceName)
+ .bucketName(bucketName)
+ .objectName(fileName)
+ .build());
+
+ if (getObjectResponse.getContentLength() == 0) {
+ LOGGER.log(Level.SEVERE, "GetObjectResponse is empty");
+ response.status(Http.Status.NOT_FOUND_404).send();
+ return;
+ }
+
+ try (InputStream fileStream = getObjectResponse.getInputStream()) {
+ byte[] objectContent = fileStream.readAllBytes();
+ response
+ .status(Http.Status.OK_200)
+ .header(Http.Header.CONTENT_DISPOSITION.defaultCase(), "attachment; filename=\"" + fileName + "\"")
+ .header("opc-request-id", getObjectResponse.getOpcRequestId())
+ .header(Http.Header.CONTENT_LENGTH.defaultCase(), getObjectResponse.getContentLength().toString());
+
+ response.send(objectContent);
+ } catch (IOException e) {
+ LOGGER.log(Level.SEVERE, "Error processing GetObjectResponse", e);
+ response.status(Http.Status.INTERNAL_SERVER_ERROR_500).send();
+ }
+ }
+
+ /**
+ * Upload a file to object storage.
+ *
+ * @param request request
+ * @param response response
+ */
+ public void upload(ServerRequest request, ServerResponse response) {
+ String fileName = request.path().pathParameters().value("fileName");
+ PutObjectRequest putObjectRequest = null;
+ try (InputStream stream = new FileInputStream(System.getProperty("user.dir") + File.separator + fileName)) {
+ byte[] contents = stream.readAllBytes();
+ putObjectRequest =
+ PutObjectRequest.builder()
+ .namespaceName(namespaceName)
+ .bucketName(bucketName)
+ .objectName(fileName)
+ .putObjectBody(new ByteArrayInputStream(contents))
+ .contentLength(Long.valueOf(contents.length))
+ .build();
+ } catch (IOException e) {
+ LOGGER.log(Level.SEVERE, "Error creating PutObjectRequest", e);
+ response.status(Http.Status.INTERNAL_SERVER_ERROR_500).send();
+ return;
+ }
+ PutObjectResponse putObjectResponse = objectStorageClient.putObject(putObjectRequest);
+
+ response.status(Http.Status.OK_200).header("opc-request-id", putObjectResponse.getOpcRequestId());
+
+ response.send();
+ }
+
+ /**
+ * Delete a file from object storage.
+ *
+ * @param request request
+ * @param response response
+ */
+ public void delete(ServerRequest request, ServerResponse response) {
+ String fileName = request.path().pathParameters().value("file-name");
+ DeleteObjectResponse deleteObjectResponse = objectStorageClient.deleteObject(DeleteObjectRequest.builder()
+ .namespaceName(namespaceName)
+ .bucketName(bucketName)
+ .objectName(fileName)
+ .build());
+ response.status(Http.Status.OK_200).header("opc-request-id", deleteObjectResponse.getOpcRequestId());
+
+ response.send();
+ }
+}
diff --git a/examples/integrations/oci/objectstorage/src/main/java/io/helidon/examples/integrations/oci/objecstorage/OciObjectStorageMain.java b/examples/integrations/oci/objectstorage/src/main/java/io/helidon/examples/integrations/oci/objecstorage/OciObjectStorageMain.java
new file mode 100644
index 00000000000..16a882fa870
--- /dev/null
+++ b/examples/integrations/oci/objectstorage/src/main/java/io/helidon/examples/integrations/oci/objecstorage/OciObjectStorageMain.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2021, 2023 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.examples.integrations.oci.objecstorage;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Supplier;
+
+import io.helidon.config.Config;
+import io.helidon.config.spi.ConfigSource;
+import io.helidon.nima.webserver.WebServer;
+import io.helidon.nima.webserver.http.HttpRouting;
+
+import static io.helidon.config.ConfigSources.classpath;
+import static io.helidon.config.ConfigSources.file;
+
+/**
+ * Main class of the example.
+ * This example sets up a web server to serve REST API to upload/download/delete objects.
+ */
+public final class OciObjectStorageMain {
+
+ private static Config config;
+
+ private OciObjectStorageMain() {
+ }
+
+ /**
+ * Main method.
+ *
+ * @param args ignored
+ */
+ public static void main(String[] args) {
+
+ config = Config
+ .builder()
+ .sources(examplesConfig())
+ .build();
+
+ WebServer server = WebServer.builder()
+ .routing(OciObjectStorageMain::routing)
+ .config(config.get("server"))
+ .start();
+ }
+
+ /**
+ * Updates HTTP Routing.
+ */
+ static void routing(HttpRouting.Builder routing) {
+ ObjectStorageService objectStorageService = new ObjectStorageService(config);
+ routing.register("/files", objectStorageService);
+ }
+
+ private static List> examplesConfig() {
+ List> suppliers = new ArrayList<>();
+ Path path = Paths.get(System.getProperty("user.home") + "/helidon/conf/examples.yaml");
+ if (Files.exists(path)) {
+ suppliers.add(file(path).build());
+ }
+ suppliers.add(classpath("application.yaml").build());
+ return suppliers;
+ }
+}
diff --git a/examples/integrations/oci/objectstorage/src/main/java/io/helidon/examples/integrations/oci/objecstorage/package-info.java b/examples/integrations/oci/objectstorage/src/main/java/io/helidon/examples/integrations/oci/objecstorage/package-info.java
new file mode 100644
index 00000000000..1a91fa72fe8
--- /dev/null
+++ b/examples/integrations/oci/objectstorage/src/main/java/io/helidon/examples/integrations/oci/objecstorage/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021, 2023 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.
+ */
+
+/**
+ * Example of integration with OCI object storage in Nima application.
+ */
+package io.helidon.examples.integrations.oci.objecstorage;
diff --git a/examples/integrations/oci/objectstorage-reactive/src/main/resources/application.yaml b/examples/integrations/oci/objectstorage/src/main/resources/application.yaml
similarity index 92%
rename from examples/integrations/oci/objectstorage-reactive/src/main/resources/application.yaml
rename to examples/integrations/oci/objectstorage/src/main/resources/application.yaml
index 4c07c154bc6..75e202bd486 100644
--- a/examples/integrations/oci/objectstorage-reactive/src/main/resources/application.yaml
+++ b/examples/integrations/oci/objectstorage/src/main/resources/application.yaml
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2021, 2022 Oracle and/or its affiliates.
+# Copyright (c) 2021, 2023 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.
diff --git a/examples/integrations/oci/atp-reactive/src/main/resources/logging.properties b/examples/integrations/oci/objectstorage/src/main/resources/logging.properties
similarity index 94%
rename from examples/integrations/oci/atp-reactive/src/main/resources/logging.properties
rename to examples/integrations/oci/objectstorage/src/main/resources/logging.properties
index 43cd0f29d7d..c09e76d612c 100644
--- a/examples/integrations/oci/atp-reactive/src/main/resources/logging.properties
+++ b/examples/integrations/oci/objectstorage/src/main/resources/logging.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2021, 2022 Oracle and/or its affiliates.
+# Copyright (c) 2021, 2023 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.
diff --git a/examples/integrations/oci/pom.xml b/examples/integrations/oci/pom.xml
index 586da771869..e896103ba23 100644
--- a/examples/integrations/oci/pom.xml
+++ b/examples/integrations/oci/pom.xml
@@ -33,12 +33,12 @@
Examples of integration with OCI (Oracle Cloud).
- atp-reactive
+ atpatp-cdi
- metrics-reactive
- objectstorage-reactive
+ metrics
+ objectstorageobjectstorage-cdi
- vault-reactive
+ vaultvault-cdi
diff --git a/examples/integrations/oci/vault-cdi/pom.xml b/examples/integrations/oci/vault-cdi/pom.xml
index e419c413b6e..43823bd348c 100644
--- a/examples/integrations/oci/vault-cdi/pom.xml
+++ b/examples/integrations/oci/vault-cdi/pom.xml
@@ -87,7 +87,7 @@
- org.jboss.jandex
+ io.smallryejandex-maven-plugin
diff --git a/examples/integrations/oci/vault-reactive/src/main/java/io/helidon/examples/integrations/oci/vault/reactive/OciHandler.java b/examples/integrations/oci/vault-reactive/src/main/java/io/helidon/examples/integrations/oci/vault/reactive/OciHandler.java
deleted file mode 100644
index 1eee9e8b5f2..00000000000
--- a/examples/integrations/oci/vault-reactive/src/main/java/io/helidon/examples/integrations/oci/vault/reactive/OciHandler.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.examples.integrations.oci.vault.reactive;
-
-import java.util.function.Consumer;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.oracle.bmc.responses.AsyncHandler;
-
-final class OciHandler {
- private static final Logger LOGGER = Logger.getLogger(OciHandler.class.getName());
-
- private OciHandler() {
- }
-
- static AsyncHandler ociHandler(Consumer handler) {
- return new AsyncHandler<>() {
- @Override
- public void onSuccess(REQ req, RES res) {
- handler.accept(res);
- }
-
- @Override
- public void onError(REQ req, Throwable error) {
- LOGGER.log(Level.WARNING, "OCI Exception", error);
- if (error instanceof Error) {
- throw (Error) error;
- }
- if (error instanceof RuntimeException) {
- throw (RuntimeException) error;
- }
- throw new RuntimeException(error);
- }
- };
- }
-}
diff --git a/examples/integrations/oci/vault-reactive/src/main/java/io/helidon/examples/integrations/oci/vault/reactive/VaultService.java b/examples/integrations/oci/vault-reactive/src/main/java/io/helidon/examples/integrations/oci/vault/reactive/VaultService.java
deleted file mode 100644
index 492b8ff29f2..00000000000
--- a/examples/integrations/oci/vault-reactive/src/main/java/io/helidon/examples/integrations/oci/vault/reactive/VaultService.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2021, 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.examples.integrations.oci.vault.reactive;
-
-import java.time.Instant;
-import java.time.temporal.ChronoUnit;
-import java.util.Date;
-
-import io.helidon.common.Base64Value;
-import io.helidon.reactive.webserver.Handler;
-import io.helidon.reactive.webserver.Routing;
-import io.helidon.reactive.webserver.ServerRequest;
-import io.helidon.reactive.webserver.ServerResponse;
-import io.helidon.reactive.webserver.Service;
-
-import com.oracle.bmc.keymanagement.KmsCryptoAsync;
-import com.oracle.bmc.keymanagement.model.DecryptDataDetails;
-import com.oracle.bmc.keymanagement.model.EncryptDataDetails;
-import com.oracle.bmc.keymanagement.model.SignDataDetails;
-import com.oracle.bmc.keymanagement.model.VerifyDataDetails;
-import com.oracle.bmc.keymanagement.requests.DecryptRequest;
-import com.oracle.bmc.keymanagement.requests.EncryptRequest;
-import com.oracle.bmc.keymanagement.requests.SignRequest;
-import com.oracle.bmc.keymanagement.requests.VerifyRequest;
-import com.oracle.bmc.secrets.SecretsAsync;
-import com.oracle.bmc.secrets.model.Base64SecretBundleContentDetails;
-import com.oracle.bmc.secrets.model.SecretBundleContentDetails;
-import com.oracle.bmc.secrets.requests.GetSecretBundleRequest;
-import com.oracle.bmc.vault.VaultsAsync;
-import com.oracle.bmc.vault.model.Base64SecretContentDetails;
-import com.oracle.bmc.vault.model.CreateSecretDetails;
-import com.oracle.bmc.vault.model.ScheduleSecretDeletionDetails;
-import com.oracle.bmc.vault.model.SecretContentDetails;
-import com.oracle.bmc.vault.requests.CreateSecretRequest;
-import com.oracle.bmc.vault.requests.ScheduleSecretDeletionRequest;
-
-import static io.helidon.examples.integrations.oci.vault.reactive.OciHandler.ociHandler;
-
-class VaultService implements Service {
- private final SecretsAsync secrets;
- private final VaultsAsync vaults;
- private final KmsCryptoAsync crypto;
- private final String vaultOcid;
- private final String compartmentOcid;
- private final String encryptionKeyOcid;
- private final String signatureKeyOcid;
-
- VaultService(SecretsAsync secrets,
- VaultsAsync vaults,
- KmsCryptoAsync crypto,
- String vaultOcid,
- String compartmentOcid,
- String encryptionKeyOcid,
- String signatureKeyOcid) {
- this.secrets = secrets;
- this.vaults = vaults;
- this.crypto = crypto;
- this.vaultOcid = vaultOcid;
- this.compartmentOcid = compartmentOcid;
- this.encryptionKeyOcid = encryptionKeyOcid;
- this.signatureKeyOcid = signatureKeyOcid;
- }
-
- @Override
- public void update(Routing.Rules rules) {
- rules.get("/encrypt/{text:.*}", this::encrypt)
- .get("/decrypt/{text:.*}", this::decrypt)
- .get("/sign/{text}", this::sign)
- .post("/verify/{text}", Handler.create(String.class, this::verify))
- .get("/secret/{id}", this::getSecret)
- .post("/secret/{name}", Handler.create(String.class, this::createSecret))
- .delete("/secret/{id}", this::deleteSecret);
- }
-
- private void getSecret(ServerRequest req, ServerResponse res) {
- secrets.getSecretBundle(GetSecretBundleRequest.builder()
- .secretId(req.path().param("id"))
- .build(), ociHandler(ociRes -> {
- SecretBundleContentDetails content = ociRes.getSecretBundle().getSecretBundleContent();
- if (content instanceof Base64SecretBundleContentDetails) {
- // the only supported type
- res.send(Base64Value.createFromEncoded(((Base64SecretBundleContentDetails) content).getContent())
- .toDecodedString());
- } else {
- req.next(new Exception("Invalid secret content type"));
- }
- }));
- }
-
- private void deleteSecret(ServerRequest req, ServerResponse res) {
- // has to be for quite a long period of time - did not work with less than 30 days
- Date deleteTime = Date.from(Instant.now().plus(30, ChronoUnit.DAYS));
-
- String secretOcid = req.path().param("id");
-
- vaults.scheduleSecretDeletion(ScheduleSecretDeletionRequest.builder()
- .secretId(secretOcid)
- .scheduleSecretDeletionDetails(ScheduleSecretDeletionDetails.builder()
- .timeOfDeletion(deleteTime)
- .build())
- .build(), ociHandler(ociRes -> res.send("Secret " + secretOcid
- + " was marked for deletion")));
- }
-
- private void createSecret(ServerRequest req, ServerResponse res, String secretText) {
- SecretContentDetails content = Base64SecretContentDetails.builder()
- .content(Base64Value.create(secretText).toBase64())
- .build();
-
- vaults.createSecret(CreateSecretRequest.builder()
- .createSecretDetails(CreateSecretDetails.builder()
- .secretName(req.path().param("name"))
- .vaultId(vaultOcid)
- .compartmentId(compartmentOcid)
- .keyId(encryptionKeyOcid)
- .secretContent(content)
- .build())
- .build(), ociHandler(ociRes -> res.send(ociRes.getSecret().getId())));
- }
-
- private void verify(ServerRequest req, ServerResponse res, String signature) {
- String text = req.path().param("text");
- VerifyDataDetails.SigningAlgorithm algorithm = VerifyDataDetails.SigningAlgorithm.Sha224RsaPkcsPss;
-
- crypto.verify(VerifyRequest.builder()
- .verifyDataDetails(VerifyDataDetails.builder()
- .keyId(signatureKeyOcid)
- .signingAlgorithm(algorithm)
- .message(Base64Value.create(text).toBase64())
- .signature(signature)
- .build())
- .build(),
- ociHandler(ociRes -> {
- boolean valid = ociRes.getVerifiedData()
- .getIsSignatureValid();
- res.send(valid ? "Signature valid" : "Signature not valid");
- }));
- }
-
- private void sign(ServerRequest req, ServerResponse res) {
- crypto.sign(SignRequest.builder()
- .signDataDetails(SignDataDetails.builder()
- .keyId(signatureKeyOcid)
- .signingAlgorithm(SignDataDetails.SigningAlgorithm.Sha224RsaPkcsPss)
- .message(Base64Value.create(req.path().param("text")).toBase64())
- .build())
- .build(), ociHandler(ociRes -> res.send(ociRes.getSignedData()
- .getSignature())));
- }
-
- private void encrypt(ServerRequest req, ServerResponse res) {
- crypto.encrypt(EncryptRequest.builder()
- .encryptDataDetails(EncryptDataDetails.builder()
- .keyId(encryptionKeyOcid)
- .plaintext(Base64Value.create(req.path().param("text")).toBase64())
- .build())
- .build(), ociHandler(ociRes -> res.send(ociRes.getEncryptedData().getCiphertext())));
- }
-
- private void decrypt(ServerRequest req, ServerResponse res) {
- crypto.decrypt(DecryptRequest.builder()
- .decryptDataDetails(DecryptDataDetails.builder()
- .keyId(encryptionKeyOcid)
- .ciphertext(req.path().param("text"))
- .build())
- .build(), ociHandler(ociRes -> res.send(Base64Value.createFromEncoded(ociRes.getDecryptedData()
- .getPlaintext())
- .toDecodedString())));
- }
-}
diff --git a/examples/integrations/oci/vault-reactive/src/main/java/io/helidon/examples/integrations/oci/vault/reactive/package-info.java b/examples/integrations/oci/vault-reactive/src/main/java/io/helidon/examples/integrations/oci/vault/reactive/package-info.java
deleted file mode 100644
index 23e07e67fd2..00000000000
--- a/examples/integrations/oci/vault-reactive/src/main/java/io/helidon/examples/integrations/oci/vault/reactive/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2021 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.
- */
-
-/**
- * Example of OCI Vault integration in a reactive application.
- */
-package io.helidon.examples.integrations.oci.vault.reactive;
diff --git a/examples/integrations/oci/vault-reactive/pom.xml b/examples/integrations/oci/vault/pom.xml
similarity index 85%
rename from examples/integrations/oci/vault-reactive/pom.xml
rename to examples/integrations/oci/vault/pom.xml
index f3ef3e400ed..588d6642305 100644
--- a/examples/integrations/oci/vault-reactive/pom.xml
+++ b/examples/integrations/oci/vault/pom.xml
@@ -29,18 +29,18 @@
io.helidon.examples.integrations.oci
- helidon-examples-integrations-oci-vault-reactive
- Helidon Examples Integration OCI Vault Reactive
- Reactive integration with OCI Vault.
+ helidon-examples-integrations-oci-vault
+ Helidon Examples Integration OCI Vault
+ Nima integration with OCI Vault.
- io.helidon.examples.integrations.oci.vault.reactive.OciVaultMain
+ io.helidon.examples.integrations.oci.vault.OciVaultMain
- io.helidon.reactive.webserver
- helidon-reactive-webserver
+ io.helidon.nima.webserver
+ helidon-nima-webserverio.helidon.config
diff --git a/examples/integrations/oci/vault-reactive/src/main/java/io/helidon/examples/integrations/oci/vault/reactive/OciVaultMain.java b/examples/integrations/oci/vault/src/main/java/io/helidon/examples/integrations/oci/vault/OciVaultMain.java
similarity index 64%
rename from examples/integrations/oci/vault-reactive/src/main/java/io/helidon/examples/integrations/oci/vault/reactive/OciVaultMain.java
rename to examples/integrations/oci/vault/src/main/java/io/helidon/examples/integrations/oci/vault/OciVaultMain.java
index 51581058603..0d3cc69b323 100644
--- a/examples/integrations/oci/vault-reactive/src/main/java/io/helidon/examples/integrations/oci/vault/reactive/OciVaultMain.java
+++ b/examples/integrations/oci/vault/src/main/java/io/helidon/examples/integrations/oci/vault/OciVaultMain.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2021, 2023 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.
@@ -14,25 +14,24 @@
* limitations under the License.
*/
-package io.helidon.examples.integrations.oci.vault.reactive;
+package io.helidon.examples.integrations.oci.vault;
import java.io.IOException;
-import io.helidon.logging.common.LogConfig;
import io.helidon.config.Config;
-import io.helidon.reactive.webserver.Routing;
-import io.helidon.reactive.webserver.WebServer;
+import io.helidon.logging.common.LogConfig;
+import io.helidon.nima.webserver.WebServer;
import com.oracle.bmc.ConfigFileReader;
import com.oracle.bmc.auth.AuthenticationDetailsProvider;
import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider;
-import com.oracle.bmc.keymanagement.KmsCryptoAsync;
-import com.oracle.bmc.keymanagement.KmsCryptoAsyncClient;
+import com.oracle.bmc.keymanagement.KmsCrypto;
+import com.oracle.bmc.keymanagement.KmsCryptoClient;
import com.oracle.bmc.model.BmcException;
-import com.oracle.bmc.secrets.SecretsAsync;
-import com.oracle.bmc.secrets.SecretsAsyncClient;
-import com.oracle.bmc.vault.VaultsAsync;
-import com.oracle.bmc.vault.VaultsAsyncClient;
+import com.oracle.bmc.secrets.Secrets;
+import com.oracle.bmc.secrets.SecretsClient;
+import com.oracle.bmc.vault.Vaults;
+import com.oracle.bmc.vault.VaultsClient;
import static io.helidon.config.ConfigSources.classpath;
import static io.helidon.config.ConfigSources.file;
@@ -70,28 +69,28 @@ public static void main(String[] args) throws IOException {
// ~/.oci/config
AuthenticationDetailsProvider authProvider = new ConfigFileAuthenticationDetailsProvider(ConfigFileReader.parseDefault());
- SecretsAsync secrets = SecretsAsyncClient.builder().build(authProvider);
- KmsCryptoAsync crypto = KmsCryptoAsyncClient.builder()
+ Secrets secrets = SecretsClient.builder().build(authProvider);
+ KmsCrypto crypto = KmsCryptoClient.builder()
.endpoint(cryptoEndpoint)
.build(authProvider);
- VaultsAsync vaults = VaultsAsyncClient.builder().build(authProvider);
+ Vaults vaults = VaultsClient.builder().build(authProvider);
- WebServer.builder()
+ WebServer server = WebServer.builder()
+ .routing(routing -> routing
+ .register("/vault", new VaultService(secrets,
+ vaults,
+ crypto,
+ vaultOcid,
+ compartmentOcid,
+ encryptionKey,
+ signatureKey))
+ .error(BmcException.class, (req, res, ex) -> res.status(
+ ex.getStatusCode()).send(ex.getMessage())))
.config(config.get("server"))
- .routing(Routing.builder()
- .register("/vault", new VaultService(secrets,
- vaults,
- crypto,
- vaultOcid,
- compartmentOcid,
- encryptionKey,
- signatureKey))
- // OCI SDK error handling
- .error(BmcException.class, (req, res, ex) -> res.status(ex.getStatusCode())
- .send(ex.getMessage())))
- .build()
- .start()
- .await();
+ .start();
+
+ System.out.println("WEB server is up! http://localhost:" + server.port());
+
}
private static Config buildConfig() {
diff --git a/examples/integrations/oci/vault/src/main/java/io/helidon/examples/integrations/oci/vault/VaultService.java b/examples/integrations/oci/vault/src/main/java/io/helidon/examples/integrations/oci/vault/VaultService.java
new file mode 100644
index 00000000000..3b7bf256858
--- /dev/null
+++ b/examples/integrations/oci/vault/src/main/java/io/helidon/examples/integrations/oci/vault/VaultService.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2021, 2023 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.examples.integrations.oci.vault;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.Date;
+import java.util.function.Consumer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import io.helidon.common.Base64Value;
+import io.helidon.common.http.Http;
+import io.helidon.nima.webserver.http.HttpRules;
+import io.helidon.nima.webserver.http.HttpService;
+import io.helidon.nima.webserver.http.ServerRequest;
+import io.helidon.nima.webserver.http.ServerResponse;
+
+import com.oracle.bmc.keymanagement.KmsCrypto;
+import com.oracle.bmc.keymanagement.model.DecryptDataDetails;
+import com.oracle.bmc.keymanagement.model.EncryptDataDetails;
+import com.oracle.bmc.keymanagement.model.SignDataDetails;
+import com.oracle.bmc.keymanagement.model.VerifyDataDetails;
+import com.oracle.bmc.keymanagement.requests.DecryptRequest;
+import com.oracle.bmc.keymanagement.requests.EncryptRequest;
+import com.oracle.bmc.keymanagement.requests.SignRequest;
+import com.oracle.bmc.keymanagement.requests.VerifyRequest;
+import com.oracle.bmc.keymanagement.responses.DecryptResponse;
+import com.oracle.bmc.keymanagement.responses.EncryptResponse;
+import com.oracle.bmc.keymanagement.responses.SignResponse;
+import com.oracle.bmc.keymanagement.responses.VerifyResponse;
+import com.oracle.bmc.secrets.Secrets;
+import com.oracle.bmc.secrets.model.Base64SecretBundleContentDetails;
+import com.oracle.bmc.secrets.model.SecretBundleContentDetails;
+import com.oracle.bmc.secrets.requests.GetSecretBundleRequest;
+import com.oracle.bmc.secrets.responses.GetSecretBundleResponse;
+import com.oracle.bmc.vault.Vaults;
+import com.oracle.bmc.vault.model.Base64SecretContentDetails;
+import com.oracle.bmc.vault.model.CreateSecretDetails;
+import com.oracle.bmc.vault.model.ScheduleSecretDeletionDetails;
+import com.oracle.bmc.vault.model.SecretContentDetails;
+import com.oracle.bmc.vault.requests.CreateSecretRequest;
+import com.oracle.bmc.vault.requests.ScheduleSecretDeletionRequest;
+import com.oracle.bmc.vault.responses.CreateSecretResponse;
+
+class VaultService implements HttpService {
+
+ private static final Logger LOGGER = Logger.getLogger(VaultService.class.getName());
+ private final Secrets secrets;
+ private final Vaults vaults;
+ private final KmsCrypto crypto;
+ private final String vaultOcid;
+ private final String compartmentOcid;
+ private final String encryptionKeyOcid;
+ private final String signatureKeyOcid;
+
+ VaultService(Secrets secrets,
+ Vaults vaults,
+ KmsCrypto crypto,
+ String vaultOcid,
+ String compartmentOcid,
+ String encryptionKeyOcid,
+ String signatureKeyOcid) {
+ this.secrets = secrets;
+ this.vaults = vaults;
+ this.crypto = crypto;
+ this.vaultOcid = vaultOcid;
+ this.compartmentOcid = compartmentOcid;
+ this.encryptionKeyOcid = encryptionKeyOcid;
+ this.signatureKeyOcid = signatureKeyOcid;
+ }
+
+ /**
+ * A service registers itself by updating the routine rules.
+ *
+ * @param rules the routing rules.
+ */
+ @Override
+ public void routing(HttpRules rules) {
+ rules.get("/encrypt/{text:.*}", this::encrypt)
+ .get("/decrypt/{text:.*}", this::decrypt)
+ .get("/sign/{text}", this::sign)
+ .post("/verify/{text}", this::verify)
+ .get("/secret/{id}", this::getSecret)
+ .post("/secret/{name}", this::createSecret)
+ .delete("/secret/{id}", this::deleteSecret);
+ }
+
+ private void getSecret(ServerRequest req, ServerResponse res) {
+ ociHandler(response -> {
+ GetSecretBundleResponse id = secrets.getSecretBundle(GetSecretBundleRequest.builder()
+ .secretId(req.path().pathParameters().value("id"))
+ .build());
+ SecretBundleContentDetails content = id.getSecretBundle().getSecretBundleContent();
+ if (content instanceof Base64SecretBundleContentDetails) {
+ // the only supported type
+ res.send(Base64Value.createFromEncoded(((Base64SecretBundleContentDetails) content).getContent())
+ .toDecodedString());
+ } else {
+ res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send("Invalid secret content type");
+ }
+ }, res);
+
+ }
+
+ private void deleteSecret(ServerRequest req, ServerResponse res) {
+ ociHandler(response -> {
+ // has to be for quite a long period of time - did not work with less than 30 days
+ Date deleteTime = Date.from(Instant.now().plus(30, ChronoUnit.DAYS));
+ String secretOcid = req.path().pathParameters().value("id");
+ vaults.scheduleSecretDeletion(ScheduleSecretDeletionRequest.builder()
+ .secretId(secretOcid)
+ .scheduleSecretDeletionDetails(ScheduleSecretDeletionDetails.builder()
+ .timeOfDeletion(deleteTime)
+ .build())
+ .build()
+ );
+ response.send(String.format("Secret %s was marked for deletion", secretOcid));
+ }, res);
+ }
+
+ private void createSecret(ServerRequest req, ServerResponse res) {
+ ociHandler(response -> {
+ String secretText = req.content().as(String.class);
+ SecretContentDetails content = Base64SecretContentDetails.builder()
+ .content(Base64Value.create(secretText).toBase64())
+ .build();
+ CreateSecretResponse vaultsSecret = vaults.createSecret(CreateSecretRequest.builder()
+ .createSecretDetails(CreateSecretDetails.builder()
+ .secretName(req.path().pathParameters().value("name"))
+ .vaultId(vaultOcid)
+ .compartmentId(compartmentOcid)
+ .keyId(encryptionKeyOcid)
+ .secretContent(content)
+ .build())
+ .build());
+ response.send(vaultsSecret.getSecret().getId());
+ }, res);
+ }
+
+ private void verify(ServerRequest req, ServerResponse res) {
+
+
+ ociHandler(response -> {
+ String text = req.path().pathParameters().value("text");
+ String signature = req.content().as(String.class);
+ VerifyDataDetails.SigningAlgorithm algorithm = VerifyDataDetails.SigningAlgorithm.Sha224RsaPkcsPss;
+ VerifyResponse verifyResponse = crypto.verify(VerifyRequest.builder()
+ .verifyDataDetails(VerifyDataDetails.builder()
+ .keyId(signatureKeyOcid)
+ .signingAlgorithm(algorithm)
+ .message(Base64Value.create(text).toBase64())
+ .signature(signature)
+ .build())
+ .build());
+ boolean valid = verifyResponse.getVerifiedData().getIsSignatureValid();
+ response.send(valid ? "Signature valid" : "Signature not valid");
+ }, res);
+ }
+
+ private void sign(ServerRequest req, ServerResponse res) {
+ ociHandler(response -> {
+ SignResponse signResponse = crypto.sign(SignRequest.builder()
+ .signDataDetails(SignDataDetails.builder()
+ .keyId(signatureKeyOcid)
+ .signingAlgorithm(SignDataDetails.SigningAlgorithm.Sha224RsaPkcsPss)
+ .message(Base64Value.create(req.path()
+ .pathParameters().value("text")).toBase64())
+ .build())
+ .build());
+ response.send(signResponse.getSignedData().getSignature());
+ }, res);
+ }
+
+ private void encrypt(ServerRequest req, ServerResponse res) {
+ ociHandler(response -> {
+ EncryptResponse encryptResponse = crypto.encrypt(EncryptRequest.builder()
+ .encryptDataDetails(EncryptDataDetails.builder()
+ .keyId(encryptionKeyOcid)
+ .plaintext(Base64Value.create(req.path()
+ .pathParameters().value("text")).toBase64())
+ .build())
+ .build());
+ response.send(encryptResponse.getEncryptedData().getCiphertext());
+ }, res);
+ }
+
+ private void decrypt(ServerRequest req, ServerResponse res) {
+ ociHandler(response -> {
+ DecryptResponse decryptResponse = crypto.decrypt(DecryptRequest.builder()
+ .decryptDataDetails(DecryptDataDetails.builder()
+ .keyId(encryptionKeyOcid)
+ .ciphertext(req.path()
+ .pathParameters().value("text"))
+ .build())
+ .build());
+ response.send(Base64Value.createFromEncoded(decryptResponse.getDecryptedData().getPlaintext())
+ .toDecodedString());
+ }, res);
+ }
+
+ private void ociHandler(Consumer consumer, ServerResponse response) {
+ try {
+ consumer.accept(response);
+ } catch (Throwable error) {
+ LOGGER.log(Level.WARNING, "OCI Exception", error);
+ response.status(Http.Status.INTERNAL_SERVER_ERROR_500).send(error.getMessage());
+ }
+ }
+}
diff --git a/examples/integrations/oci/vault/src/main/java/io/helidon/examples/integrations/oci/vault/package-info.java b/examples/integrations/oci/vault/src/main/java/io/helidon/examples/integrations/oci/vault/package-info.java
new file mode 100644
index 00000000000..deea60af35b
--- /dev/null
+++ b/examples/integrations/oci/vault/src/main/java/io/helidon/examples/integrations/oci/vault/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021, 2023 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.
+ */
+
+/**
+ * Example of OCI Vault integration in a Nima application.
+ */
+package io.helidon.examples.integrations.oci.vault;
diff --git a/examples/integrations/oci/vault-reactive/src/main/resources/application.yaml b/examples/integrations/oci/vault/src/main/resources/application.yaml
similarity index 95%
rename from examples/integrations/oci/vault-reactive/src/main/resources/application.yaml
rename to examples/integrations/oci/vault/src/main/resources/application.yaml
index 982ef550c45..a61582e97b5 100644
--- a/examples/integrations/oci/vault-reactive/src/main/resources/application.yaml
+++ b/examples/integrations/oci/vault/src/main/resources/application.yaml
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2021, 2022 Oracle and/or its affiliates.
+# Copyright (c) 2021, 2023 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.
diff --git a/examples/integrations/oci/metrics-reactive/src/main/resources/logging.properties b/examples/integrations/oci/vault/src/main/resources/logging.properties
similarity index 94%
rename from examples/integrations/oci/metrics-reactive/src/main/resources/logging.properties
rename to examples/integrations/oci/vault/src/main/resources/logging.properties
index f8802f90626..341cef8ce9e 100644
--- a/examples/integrations/oci/metrics-reactive/src/main/resources/logging.properties
+++ b/examples/integrations/oci/vault/src/main/resources/logging.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2021, 2022 Oracle and/or its affiliates.
+# Copyright (c) 2021, 2023 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.
diff --git a/examples/integrations/vault/hcp-cdi/pom.xml b/examples/integrations/vault/hcp-cdi/pom.xml
index e4fb29b92b3..79346a8154d 100644
--- a/examples/integrations/vault/hcp-cdi/pom.xml
+++ b/examples/integrations/vault/hcp-cdi/pom.xml
@@ -87,7 +87,7 @@
- org.jboss.jandex
+ io.smallryejandex-maven-plugin
diff --git a/examples/jbatch/pom.xml b/examples/jbatch/pom.xml
index e1f7c9cc0f7..56bdea51824 100644
--- a/examples/jbatch/pom.xml
+++ b/examples/jbatch/pom.xml
@@ -68,7 +68,7 @@
- org.jboss
+ io.smallryejandexruntimetrue
@@ -124,7 +124,7 @@
- org.jboss.jandex
+ io.smallryejandex-maven-plugin
diff --git a/examples/logging/jul/README.md b/examples/logging/jul/README.md
index 07b3df804af..1d86b469683 100644
--- a/examples/logging/jul/README.md
+++ b/examples/logging/jul/README.md
@@ -20,11 +20,11 @@ java -jar target/helidon-examples-logging-jul.jar
Expected output should be similar to the following:
```text
-2020.11.19 15:37:28 INFO io.helidon.logging.common.LogConfig Thread[main,5,main]: Logging at initialization configured using classpath: /logging.properties ""
+2020.11.19 15:37:28 INFO io.helidon.logging.jul.JulProvider Thread[#1,main,5,main]: Logging at initialization configured using classpath: /logging.properties ""
2020.11.19 15:37:28 INFO io.helidon.examples.logging.jul.Main Thread[main,5,main]: Starting up "startup"
2020.11.19 15:37:28 INFO io.helidon.examples.logging.jul.Main Thread[pool-1-thread-1,5,main]: Running on another thread "propagated"
-2020.11.19 15:37:28 INFO io.helidon.common.features.HelidonFeatures Thread[features-thread,5,main]: Helidon SE 2.2.0 features: [Config, WebServer] ""
-2020.11.19 15:37:28 INFO io.helidon.reactive.webserver.NettyWebServer Thread[nioEventLoopGroup-2-1,10,main]: Channel '@default' started: [id: 0x8a5f5634, L:/0:0:0:0:0:0:0:0:8080] ""
+2020.11.19 15:37:28 INFO io.helidon.common.features.HelidonFeatures Thread[#23,features-thread,5,main]: Helidon NIMA 4.0.0-SNAPSHOT features: [Config, Encoding, Media, WebServer] ""
+2020.11.19 15:37:28 INFO io.helidon.nima.webserver.LoomServer Thread[#1,main,5,main]: Started all channels in 46 milliseconds. 577 milliseconds since JVM startup. Java 20.0.1+9-29 "propagated"
```
# Running as native image
diff --git a/examples/logging/jul/pom.xml b/examples/logging/jul/pom.xml
index 85791619354..ca654ccdadd 100644
--- a/examples/logging/jul/pom.xml
+++ b/examples/logging/jul/pom.xml
@@ -41,8 +41,8 @@
- io.helidon.reactive.webserver
- helidon-reactive-webserver
+ io.helidon.nima.webserver
+ helidon-nima-webserver
diff --git a/examples/logging/jul/src/main/java/io/helidon/examples/logging/jul/Main.java b/examples/logging/jul/src/main/java/io/helidon/examples/logging/jul/Main.java
index 5a9b065264f..7388ce88c2a 100644
--- a/examples/logging/jul/src/main/java/io/helidon/examples/logging/jul/Main.java
+++ b/examples/logging/jul/src/main/java/io/helidon/examples/logging/jul/Main.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2020, 2023 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.
@@ -19,15 +19,14 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import io.helidon.common.context.Context;
import io.helidon.common.context.Contexts;
import io.helidon.logging.common.HelidonMdc;
import io.helidon.logging.common.LogConfig;
-import io.helidon.reactive.webserver.Routing;
-import io.helidon.reactive.webserver.WebServer;
+import io.helidon.nima.webserver.WebServer;
+import io.helidon.nima.webserver.http.HttpRouting;
/**
* Main class of the example, runnable from command line.
@@ -51,18 +50,18 @@ public static void main(String[] args) {
// done by the webserver
Contexts.runInContext(Context.create(), Main::logging);
- WebServer.builder()
- .routing(Routing.builder()
- .get("/", (req, res) -> {
- HelidonMdc.set("name", String.valueOf(req.requestId()));
- LOGGER.info("Running in webserver, id:");
- res.send("Hello");
- })
- .build())
+ WebServer server = WebServer.builder()
.port(8080)
- .build()
- .start()
- .await(10, TimeUnit.SECONDS);
+ .routing(Main::routing)
+ .start();
+ }
+
+ private static void routing(HttpRouting.Builder routing) {
+ routing.get("/", (req, res) -> {
+ HelidonMdc.set("name", String.valueOf(req.id()));
+ LOGGER.info("Running in webserver, id:");
+ res.send("Hello");
+ });
}
private static void logging() {
diff --git a/examples/logging/log4j/README.md b/examples/logging/log4j/README.md
index d99ea402692..af9d59a9765 100644
--- a/examples/logging/log4j/README.md
+++ b/examples/logging/log4j/README.md
@@ -22,12 +22,11 @@ java -jar target/helidon-examples-logging-log4j.jar
Expected output should be similar to the following:
```text
-2020-11-19 15:44:48,561 main INFO Registered Log4j as the java.util.logging.LogManager.
15:44:48.596 INFO [main] io.helidon.examples.logging.log4j.Main - Starting up "startup"
-15:44:48.598 INFO [main] io.helidon.examples.logging.log4j.Main - Using JUL logger "startup"
+15:44:48.598 INFO [main] io.helidon.examples.logging.log4j.Main - Using System logger "startup"
15:44:48.600 INFO [pool-2-thread-1] io.helidon.examples.logging.log4j.Main - Running on another thread "propagated"
-15:44:48.704 INFO [features-thread] io.helidon.common.features.HelidonFeatures - Helidon SE 2.2.0 features: [Config, WebServer] ""
-15:44:48.801 INFO [nioEventLoopGroup-2-1] io.helidon.reactive.webserver.NettyWebServer - Channel '@default' started: [id: 0xa215c23d, L:/0:0:0:0:0:0:0:0:8080] ""
+15:44:48.704 INFO [features-thread] io.helidon.common.features.HelidonFeatures - Helidon NIMA 4.0.0-SNAPSHOT features: [Config, Encoding, Media, WebServer] ""
+15:44:48.801 INFO [main] io.helidon.nima.webserver.LoomServer - Started all channels in 12 milliseconds. 746 milliseconds since JVM startup. Java 20.0.1+9-29 "propagated"
```
# Running as native image
diff --git a/examples/logging/log4j/pom.xml b/examples/logging/log4j/pom.xml
index bab864dff43..70644e0a199 100644
--- a/examples/logging/log4j/pom.xml
+++ b/examples/logging/log4j/pom.xml
@@ -41,8 +41,8 @@
- io.helidon.reactive.webserver
- helidon-reactive-webserver
+ io.helidon.nima.webserver
+ helidon-nima-webserverio.helidon.logging
diff --git a/examples/logging/log4j/src/main/java/io/helidon/examples/logging/log4j/Main.java b/examples/logging/log4j/src/main/java/io/helidon/examples/logging/log4j/Main.java
index df0346c320a..767ece02f24 100644
--- a/examples/logging/log4j/src/main/java/io/helidon/examples/logging/log4j/Main.java
+++ b/examples/logging/log4j/src/main/java/io/helidon/examples/logging/log4j/Main.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2020, 2023 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.
@@ -19,14 +19,13 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
import io.helidon.common.context.Context;
import io.helidon.common.context.Contexts;
import io.helidon.logging.common.HelidonMdc;
import io.helidon.logging.common.LogConfig;
-import io.helidon.reactive.webserver.Routing;
-import io.helidon.reactive.webserver.WebServer;
+import io.helidon.nima.webserver.WebServer;
+import io.helidon.nima.webserver.http.HttpRouting;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
@@ -68,18 +67,17 @@ public static void main(String[] args) {
// done by the webserver
Contexts.runInContext(Context.create(), Main::logging);
- WebServer.builder()
- .routing(Routing.builder()
- .get("/", (req, res) -> {
- HelidonMdc.set("name", String.valueOf(req.requestId()));
- logger.info("Running in webserver, id:");
- res.send("Hello");
- })
- .build())
- .port(8080)
- .build()
- .start()
- .await(10, TimeUnit.SECONDS);
+ WebServer server = WebServer.builder()
+ .routing(Main::routing)
+ .start();
+ }
+
+ private static void routing(HttpRouting.Builder routing) {
+ routing.get("/", (req, res) -> {
+ HelidonMdc.set("name", String.valueOf(req.id()));
+ logger.info("Running in webserver, id:");
+ res.send("Hello");
+ });
}
private static void logging() {
diff --git a/examples/logging/logback-aot/README.md b/examples/logging/logback-aot/README.md
index 30c560c1e1b..c4a6be6559d 100644
--- a/examples/logging/logback-aot/README.md
+++ b/examples/logging/logback-aot/README.md
@@ -18,11 +18,11 @@ Within 30 seconds the configuration should be reloaded, and next request will ha
Expected output should be similar to the following (for both hotspot and native):
```text
-15:40:44.240 INFO [main] i.h.examples.logging.slf4j.Main - Starting up startup
-15:40:44.241 INFO [main] i.h.examples.logging.slf4j.Main - Using JUL logger startup
-15:40:44.245 INFO [pool-1-thread-1] i.h.examples.logging.slf4j.Main - Running on another thread propagated
-15:40:44.395 INFO [features-thread] io.helidon.common.features.HelidonFeatures - Helidon SE 2.2.0 features: [Config, WebServer]
-15:40:44.538 INFO [nioEventLoopGroup-2-1] io.helidon.reactive.webserver.NettyWebServer - Channel '@default' started: [id: 0x8e516487, L:/0:0:0:0:0:0:0:0:8080]
+15:40:44.240 [INFO ] [io.helidon.examples.logging.logback.aot.Main.logging:128] Starting up startup
+15:40:44.241 [INFO ] [o.slf4j.jdk.platform.logging.SLF4JPlatformLogger.performLog:151] Using System logger startup
+15:40:44.245 [INFO ] [io.helidon.examples.logging.logback.aot.Main.log:146] Running on another thread propagated
+15:40:44.395 [INFO ] [o.slf4j.jdk.platform.logging.SLF4JPlatformLogger.performLog:151] Helidon NIMA 4.0.0-SNAPSHOT features: [Config, Encoding, Media, WebServer]
+15:40:44.538 [INFO ] [o.slf4j.jdk.platform.logging.SLF4JPlatformLogger.performLog:151] Started all channels in 15 milliseconds. 647 milliseconds since JVM startup. Java 20.0.1+9-29 propagated
```
The output is also logged into `helidon.log`.
@@ -36,7 +36,7 @@ mvn clean package
Run from command line:
```shell script
-java -jar target/helidon-examples-logging-sfl4j.jar
+java -jar target/helidon-examples-logging-slf4j-aot.jar
```
Execute endpoint:
diff --git a/examples/logging/logback-aot/pom.xml b/examples/logging/logback-aot/pom.xml
index add733a0905..b48865b4900 100644
--- a/examples/logging/logback-aot/pom.xml
+++ b/examples/logging/logback-aot/pom.xml
@@ -42,8 +42,8 @@
- io.helidon.reactive.webserver
- helidon-reactive-webserver
+ io.helidon.nima.webserver
+ helidon-nima-webserverio.helidon.logging
diff --git a/examples/logging/logback-aot/src/main/java/io/helidon/examples/logging/logback/aot/Main.java b/examples/logging/logback-aot/src/main/java/io/helidon/examples/logging/logback/aot/Main.java
index 470b18c764b..e832f19cafc 100644
--- a/examples/logging/logback-aot/src/main/java/io/helidon/examples/logging/logback/aot/Main.java
+++ b/examples/logging/logback-aot/src/main/java/io/helidon/examples/logging/logback/aot/Main.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2021, 2023 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.
@@ -19,13 +19,12 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
import io.helidon.common.context.Context;
import io.helidon.common.context.Contexts;
import io.helidon.logging.common.HelidonMdc;
-import io.helidon.reactive.webserver.Routing;
-import io.helidon.reactive.webserver.WebServer;
+import io.helidon.nima.webserver.WebServer;
+import io.helidon.nima.webserver.http.HttpRouting;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
@@ -60,20 +59,20 @@ public static void main(String[] args) {
// done by the webserver
Contexts.runInContext(Context.create(), Main::logging);
- WebServer.builder()
- .routing(Routing.builder()
- .get("/", (req, res) -> {
- HelidonMdc.set("name", String.valueOf(req.requestId()));
- LOGGER.debug("Debug message to show runtime reloading works");
- LOGGER.info("Running in webserver, id:");
- res.send("Hello")
- .forSingle(ignored -> LOGGER.debug("Response sent"));
- })
- .build())
+ WebServer server = WebServer.builder()
.port(8080)
- .build()
- .start()
- .await(10, TimeUnit.SECONDS);
+ .routing(Main::routing)
+ .start();
+ }
+
+ private static void routing(HttpRouting.Builder routing) {
+ routing.get("/", (req, res) -> {
+ HelidonMdc.set("name", String.valueOf(req.id()));
+ LOGGER.debug("Debug message to show runtime reloading works");
+ LOGGER.info("Running in webserver, id:");
+ res.send("Hello");
+ LOGGER.debug("Response sent");
+ });
}
private static void setupLogging() {
diff --git a/examples/logging/slf4j/README.md b/examples/logging/slf4j/README.md
index d9720bfea10..ec016da0c94 100644
--- a/examples/logging/slf4j/README.md
+++ b/examples/logging/slf4j/README.md
@@ -11,10 +11,10 @@ The example can be built using GraalVM native image as well.
Expected output should be similar to the following (for both hotspot and native):
```text
15:40:44.240 INFO [main] i.h.examples.logging.slf4j.Main - Starting up startup
-15:40:44.241 INFO [main] i.h.examples.logging.slf4j.Main - Using JUL logger startup
+15:40:44.241 INFO [main] i.h.examples.logging.slf4j.Main - Using System logger startup
15:40:44.245 INFO [pool-1-thread-1] i.h.examples.logging.slf4j.Main - Running on another thread propagated
-15:40:44.395 INFO [features-thread] io.helidon.common.features.HelidonFeatures - Helidon SE 2.2.0 features: [Config, WebServer]
-15:40:44.538 INFO [nioEventLoopGroup-2-1] io.helidon.reactive.webserver.NettyWebServer - Channel '@default' started: [id: 0x8e516487, L:/0:0:0:0:0:0:0:0:8080]
+15:40:44.395 INFO [features-thread] i.h.common.features.HelidonFeatures - Helidon NIMA 4.0.0-SNAPSHOT features: [Config, Encoding, Media, WebServer]
+15:40:44.538 INFO [main] i.helidon.nima.webserver.LoomServer - Started all channels in 15 milliseconds. 561 milliseconds since JVM startup. Java 20.0.1+9-29 propagated
```
# Running as jar
diff --git a/examples/logging/slf4j/pom.xml b/examples/logging/slf4j/pom.xml
index 3a4505a43de..fb81df6a3f1 100644
--- a/examples/logging/slf4j/pom.xml
+++ b/examples/logging/slf4j/pom.xml
@@ -41,8 +41,8 @@
- io.helidon.reactive.webserver
- helidon-reactive-webserver
+ io.helidon.nima.webserver
+ helidon-nima-webserverio.helidon.logging
diff --git a/examples/logging/slf4j/src/main/java/io/helidon/examples/logging/slf4j/Main.java b/examples/logging/slf4j/src/main/java/io/helidon/examples/logging/slf4j/Main.java
index c38d1ab793d..ab1bdb3c4b5 100644
--- a/examples/logging/slf4j/src/main/java/io/helidon/examples/logging/slf4j/Main.java
+++ b/examples/logging/slf4j/src/main/java/io/helidon/examples/logging/slf4j/Main.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2020, 2023 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.
@@ -19,14 +19,13 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
import io.helidon.common.context.Context;
import io.helidon.common.context.Contexts;
import io.helidon.logging.common.HelidonMdc;
import io.helidon.logging.common.LogConfig;
-import io.helidon.reactive.webserver.Routing;
-import io.helidon.reactive.webserver.WebServer;
+import io.helidon.nima.webserver.WebServer;
+import io.helidon.nima.webserver.http.HttpRouting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -55,18 +54,17 @@ public static void main(String[] args) {
// done by the webserver
Contexts.runInContext(Context.create(), Main::logging);
- WebServer.builder()
- .routing(Routing.builder()
- .get("/", (req, res) -> {
- HelidonMdc.set("name", String.valueOf(req.requestId()));
- LOGGER.info("Running in webserver, id:");
- res.send("Hello");
- })
- .build())
- .port(8080)
- .build()
- .start()
- .await(10, TimeUnit.SECONDS);
+ WebServer server = WebServer.builder()
+ .routing(Main::routing)
+ .start();
+ }
+
+ private static void routing(HttpRouting.Builder routing) {
+ routing.get("/", (req, res) -> {
+ HelidonMdc.set("name", String.valueOf(req.id()));
+ LOGGER.info("Running in webserver, id:");
+ res.send("Hello");
+ });
}
private static void logging() {
diff --git a/examples/media/multipart/README.md b/examples/media/multipart/README.md
index 206a630c045..13acde601fe 100644
--- a/examples/media/multipart/README.md
+++ b/examples/media/multipart/README.md
@@ -1,4 +1,4 @@
-# Helidon SE MultiPart Example
+# Helidon Nima MultiPart Example
This example demonstrates how to use `MultiPartSupport` with both the `WebServer`
and `WebClient` APIs.
diff --git a/examples/media/multipart/pom.xml b/examples/media/multipart/pom.xml
index 2daf742224e..127f52bc325 100644
--- a/examples/media/multipart/pom.xml
+++ b/examples/media/multipart/pom.xml
@@ -23,9 +23,9 @@
4.0.0io.helidon.applications
- helidon-se
+ helidon-nima4.0.0-SNAPSHOT
- ../../../applications/se/pom.xml
+ ../../../applications/nima/pom.xmlio.helidon.examples.mediahelidon-examples-media-multipart
@@ -41,24 +41,24 @@
- io.helidon.reactive.webserver
- helidon-reactive-webserver
+ io.helidon.nima.webserver
+ helidon-nima-webserver
- io.helidon.reactive.webserver
- helidon-reactive-webserver-static-content
+ io.helidon.nima.http.media
+ helidon-nima-http-media-multipart
- io.helidon.reactive.media
- helidon-reactive-media-multipart
+ io.helidon.nima.http.media
+ helidon-nima-http-media-jsonp
- io.helidon.reactive.media
- helidon-reactive-media-jsonp
+ io.helidon.nima.webserver
+ helidon-nima-webserver-static-content
- org.eclipse.parsson
- parsson
+ jakarta.json
+ jakarta.json-apiorg.junit.jupiter
@@ -71,8 +71,8 @@
test
- io.helidon.reactive.webclient
- helidon-reactive-webclient
+ io.helidon.nima.testing.junit5
+ helidon-nima-testing-junit5-webservertest
@@ -90,12 +90,15 @@
org.apache.maven.plugins
- maven-compiler-plugin
-
-
- --enable-preview
-
-
+ maven-failsafe-plugin
+
+
+
+ integration-test
+ verify
+
+
+
diff --git a/examples/media/multipart/src/main/java/io/helidon/examples/media/multipart/FileService.java b/examples/media/multipart/src/main/java/io/helidon/examples/media/multipart/FileService.java
index b757d8b0741..2b3b4d5cce9 100644
--- a/examples/media/multipart/src/main/java/io/helidon/examples/media/multipart/FileService.java
+++ b/examples/media/multipart/src/main/java/io/helidon/examples/media/multipart/FileService.java
@@ -15,92 +15,136 @@
*/
package io.helidon.examples.media.multipart;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.Arrays;
+import java.nio.file.StandardOpenOption;
import java.util.Map;
-import java.util.concurrent.ExecutorService;
+import java.util.stream.Stream;
-import io.helidon.common.configurable.ThreadPoolSupplier;
-import io.helidon.common.http.BadRequestException;
import io.helidon.common.http.ContentDisposition;
-import io.helidon.common.http.DataChunk;
import io.helidon.common.http.Http;
+import io.helidon.common.http.ServerResponseHeaders;
import io.helidon.common.media.type.MediaTypes;
-import io.helidon.common.reactive.IoMulti;
-import io.helidon.reactive.media.multipart.ReadableBodyPart;
-import io.helidon.reactive.webserver.ResponseHeaders;
-import io.helidon.reactive.webserver.Routing;
-import io.helidon.reactive.webserver.ServerRequest;
-import io.helidon.reactive.webserver.ServerResponse;
-import io.helidon.reactive.webserver.Service;
+import io.helidon.nima.http.media.multipart.MultiPart;
+import io.helidon.nima.http.media.multipart.ReadablePart;
+import io.helidon.nima.webserver.http.HttpRules;
+import io.helidon.nima.webserver.http.HttpService;
+import io.helidon.nima.webserver.http.ServerRequest;
+import io.helidon.nima.webserver.http.ServerResponse;
import jakarta.json.Json;
import jakarta.json.JsonArrayBuilder;
import jakarta.json.JsonBuilderFactory;
+import static io.helidon.common.http.Http.Status.BAD_REQUEST_400;
+import static io.helidon.common.http.Http.Status.MOVED_PERMANENTLY_301;
+import static io.helidon.common.http.Http.Status.NOT_FOUND_404;
+
/**
* File service.
*/
-public final class FileService implements Service {
-
- private static final JsonBuilderFactory JSON_FACTORY = Json.createBuilderFactory(Map.of());
- private final FileStorage storage;
- private final ExecutorService executor = ThreadPoolSupplier.create("multipart-thread-pool").get();
-
+public final class FileService implements HttpService {
+ private static final Http.HeaderValue UI_LOCATION = Http.Header.createCached(Http.Header.LOCATION, "/ui");
+ private final JsonBuilderFactory jsonFactory;
+ private final Path storage;
/**
* Create a new file upload service instance.
*/
FileService() {
- storage = new FileStorage();
+ jsonFactory = Json.createBuilderFactory(Map.of());
+ storage = createStorage();
+ System.out.println("Storage: " + storage);
}
@Override
- public void update(Routing.Rules rules) {
+ public void routing(HttpRules rules) {
rules.get("/", this::list)
- .get("/{fname}", this::download)
- .post("/", this::upload);
+ .get("/{fname}", this::download)
+ .post("/", this::upload);
+ }
+
+ private static Path createStorage() {
+ try {
+ return Files.createTempDirectory("fileupload");
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private static Stream listFiles(Path storage) {
+
+ try (Stream walk = Files.walk(storage)) {
+ return walk.filter(Files::isRegularFile)
+ .map(storage::relativize)
+ .map(Path::toString)
+ .toList()
+ .stream();
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private static OutputStream newOutputStream(Path storage, String fname) {
+ try {
+ return Files.newOutputStream(storage.resolve(fname),
+ StandardOpenOption.CREATE,
+ StandardOpenOption.WRITE,
+ StandardOpenOption.TRUNCATE_EXISTING);
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
}
private void list(ServerRequest req, ServerResponse res) {
- JsonArrayBuilder arrayBuilder = JSON_FACTORY.createArrayBuilder();
- storage.listFiles().forEach(arrayBuilder::add);
- res.send(JSON_FACTORY.createObjectBuilder().add("files", arrayBuilder).build());
+ JsonArrayBuilder arrayBuilder = jsonFactory.createArrayBuilder();
+ listFiles(storage).forEach(arrayBuilder::add);
+ res.send(jsonFactory.createObjectBuilder().add("files", arrayBuilder).build());
}
private void download(ServerRequest req, ServerResponse res) {
- Path filePath = storage.lookup(req.path().param("fname"));
- ResponseHeaders headers = res.headers();
+ Path filePath = storage.resolve(req.path().pathParameters().value("fname"));
+ if (!filePath.getParent().equals(storage)) {
+ res.status(BAD_REQUEST_400).send("Invalid file name");
+ return;
+ }
+ if (!Files.exists(filePath)) {
+ res.status(NOT_FOUND_404).send();
+ return;
+ }
+ if (!Files.isRegularFile(filePath)) {
+ res.status(BAD_REQUEST_400).send("Not a file");
+ return;
+ }
+ ServerResponseHeaders headers = res.headers();
headers.contentType(MediaTypes.APPLICATION_OCTET_STREAM);
- headers.set(Http.Header.CONTENT_DISPOSITION, ContentDisposition.builder()
- .filename(filePath.getFileName().toString())
- .build()
- .toString());
+ headers.set(ContentDisposition.builder()
+ .filename(filePath.getFileName().toString())
+ .build());
res.send(filePath);
}
private void upload(ServerRequest req, ServerResponse res) {
- req.content().asStream(ReadableBodyPart.class)
- .forEach(part -> {
- if (part.isNamed("file[]")) {
- String filename = part.filename()
- .orElseThrow(() -> new BadRequestException("Missing filename"));
- part.content()
- .map(DataChunk::data)
- .flatMapIterable(Arrays::asList)
- .to(IoMulti.writeToFile(storage.create(filename))
- .executor(executor)
- .build());
- } else {
- // when streaming unconsumed parts needs to be drained
- part.drain();
- }
- })
- .onError(res::send)
- .onComplete(() -> {
- res.status(Http.Status.MOVED_PERMANENTLY_301);
- res.headers().set(Http.Header.LOCATION, "/ui");
- res.send();
- }).ignoreElement();
+ MultiPart mp = req.content().as(MultiPart.class);
+
+ while (mp.hasNext()) {
+ ReadablePart part = mp.next();
+ if ("file[]".equals(URLDecoder.decode(part.name(), StandardCharsets.UTF_8))) {
+ try (InputStream in = part.inputStream(); OutputStream out = newOutputStream(storage, part.fileName().get())) {
+ in.transferTo(out);
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to write content", e);
+ }
+ }
+ }
+
+ res.status(MOVED_PERMANENTLY_301)
+ .header(UI_LOCATION)
+ .send();
}
}
diff --git a/examples/media/multipart/src/main/java/io/helidon/examples/media/multipart/FileStorage.java b/examples/media/multipart/src/main/java/io/helidon/examples/media/multipart/FileStorage.java
deleted file mode 100644
index 8825395f665..00000000000
--- a/examples/media/multipart/src/main/java/io/helidon/examples/media/multipart/FileStorage.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2021, 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.examples.media.multipart;
-
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.stream.Stream;
-
-import io.helidon.common.http.BadRequestException;
-import io.helidon.common.http.NotFoundException;
-
-/**
- * Simple bean to managed a directory based storage.
- */
-public class FileStorage {
-
- private final Path storageDir;
-
- /**
- * Create a new instance.
- */
- public FileStorage() {
- try {
- storageDir = Files.createTempDirectory("fileupload");
- } catch (IOException ex) {
- throw new UncheckedIOException(ex);
- }
- }
-
- /**
- * Get the storage directory.
- *
- * @return directory
- */
- public Path storageDir() {
- return storageDir;
- }
-
- /**
- * Get the names of the files in the storage directory.
- *
- * @return Stream of file names
- */
- public Stream listFiles() {
- try {
- return Files.walk(storageDir)
- .filter(Files::isRegularFile)
- .map(storageDir::relativize)
- .map(java.nio.file.Path::toString);
- } catch (IOException ex) {
- throw new UncheckedIOException(ex);
- }
- }
-
- /**
- * Create a new file in the storage.
- *
- * @param fname file name
- * @return file
- * @throws BadRequestException if the resolved file is not contained in the storage directory
- */
- public Path create(String fname) {
- Path file = storageDir.resolve(fname);
- if (!file.getParent().equals(storageDir)) {
- throw new BadRequestException("Invalid file name");
- }
- try {
- Files.createFile(file);
- } catch (IOException ex) {
- throw new UncheckedIOException(ex);
- }
- return file;
- }
-
- /**
- * Lookup an existing file in the storage.
- *
- * @param fname file name
- * @return file
- * @throws NotFoundException If the resolved file does not exist
- * @throws BadRequestException if the resolved file is not contained in the storage directory
- */
- public Path lookup(String fname) {
- Path file = storageDir.resolve(fname);
- if (!file.getParent().equals(storageDir)) {
- throw new BadRequestException("Invalid file name");
- }
- if (!Files.exists(file)) {
- throw new NotFoundException("file not found");
- }
- if (!Files.isRegularFile(file)) {
- throw new BadRequestException("Not a file");
- }
- return file;
- }
-}
diff --git a/examples/media/multipart/src/main/java/io/helidon/examples/media/multipart/Main.java b/examples/media/multipart/src/main/java/io/helidon/examples/media/multipart/Main.java
index 63c82a582f9..6e9ecca0897 100644
--- a/examples/media/multipart/src/main/java/io/helidon/examples/media/multipart/Main.java
+++ b/examples/media/multipart/src/main/java/io/helidon/examples/media/multipart/Main.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2020, 2023 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.
@@ -16,75 +16,47 @@
package io.helidon.examples.media.multipart;
import io.helidon.common.http.Http;
-import io.helidon.common.reactive.Single;
-import io.helidon.logging.common.LogConfig;
-import io.helidon.reactive.media.jsonp.JsonpSupport;
-import io.helidon.reactive.media.multipart.MultiPartSupport;
-import io.helidon.reactive.webserver.Routing;
-import io.helidon.reactive.webserver.WebServer;
-import io.helidon.reactive.webserver.staticcontent.StaticContentSupport;
+import io.helidon.nima.webserver.WebServer;
+import io.helidon.nima.webserver.http.HttpRules;
+import io.helidon.nima.webserver.staticcontent.StaticContentService;
/**
* This application provides a simple file upload service with a UI to exercise multipart.
*/
public final class Main {
- private static final Http.HeaderValue REDIRECT_LOCATION = Http.Header.createCached(Http.Header.LOCATION, "/ui");
+ private static final Http.HeaderValue UI_LOCATION = Http.Header.createCached(Http.Header.LOCATION, "/ui");
private Main() {
}
/**
- * Creates new {@link Routing}.
+ * Executes the example.
*
- * @return the new instance
+ * @param args command line arguments, ignored
*/
- static Routing createRouting() {
- return Routing.builder()
- .any("/", (req, res) -> {
- res.status(Http.Status.MOVED_PERMANENTLY_301);
- res.headers().set(REDIRECT_LOCATION);
- res.send();
- })
- .register("/ui", StaticContentSupport.builder("WEB")
- .welcomeFileName("index.html")
- .build())
- .register("/api", new FileService())
- .build();
- }
+ public static void main(String[] args) {
+ WebServer server = WebServer.builder()
+ .routing(Main::routing)
+ .port(8080)
+ .start();
- /**
- * Application main entry point.
- * @param args command line arguments.
- */
- public static void main(final String[] args) {
- startServer(8080);
+ System.out.println("WEB server is up! http://localhost:" + server.port());
}
/**
- * Start the server.
- * @return the created {@link WebServer} instance
+ * Updates the routing rules.
+ *
+ * @param rules routing rules
*/
- static Single startServer(int port) {
- LogConfig.configureRuntime();
- WebServer server = WebServer.builder(createRouting())
- .port(port)
- .addMediaSupport(MultiPartSupport.create())
- .addMediaSupport(JsonpSupport.create())
- .build();
-
- Single webserver = server.start();
-
- // Start the server and print some info.
- webserver.thenAccept(ws -> {
- System.out.println("WEB server is up! http://localhost:" + ws.port());
- });
-
- // Server threads are not demon. NO need to block. Just react.
- server.whenShutdown()
- .thenRun(() -> System.out.println("WEB server is DOWN. Good bye!"));
-
- return webserver;
+ static void routing(HttpRules rules) {
+ rules.any("/", (req, res) -> {
+ res.status(Http.Status.MOVED_PERMANENTLY_301);
+ res.header(UI_LOCATION);
+ res.send();
+ })
+ .register("/ui", StaticContentService.builder("WEB")
+ .welcomeFileName("index.html")
+ .build())
+ .register("/api", new FileService());
}
-
-
}
diff --git a/examples/media/multipart/src/main/resources/WEB/index.html b/examples/media/multipart/src/main/resources/WEB/index.html
index 020d42db3f8..cc055977e07 100644
--- a/examples/media/multipart/src/main/resources/WEB/index.html
+++ b/examples/media/multipart/src/main/resources/WEB/index.html
@@ -1,7 +1,7 @@
-
-
- Helidon Examples Media Multipart
-
-
-
+
+
-
-
-