helidon | Java libraries for writing microservices | Microservice library
kandi X-RAY | helidon Summary
Support
Quality
Security
License
Reuse
- Generate a discovered method .
- Gets the parser iterator .
- Process persistence xml .
- Get the security definition for a method
- Add beans to the authentication details provider .
- Handles the response message .
- Update metrics for the given method .
- Drains the parts of the parser iterator and waits for it to finish .
- Verifies the signature .
- Initialize Jaeger configuration .
helidon Key Features
helidon Examples and Code Snippets
// 1. Create config object Config config = new Config(); config.useClusterServers() // use "rediss://" for SSL connection .addNodeAddress("redis://127.0.0.1:7181"); // or read config from file config = Config.fromYAML(new File("config-file.yaml"));
// 2. Create Redisson instance // Sync and Async API RedissonClient redisson = Redisson.create(config); // Reactive API RedissonReactiveClient redissonReactive = redisson.reactive(); // RxJava3 API RedissonRxClient redissonRx = redisson.rxJava();
// 3. Get Redis based implementation of java.util.concurrent.ConcurrentMap RMap map = redisson.getMap("myMap"); RMapReactive mapReactive = redissonReactive.getMap("myMap"); RMapRx mapRx = redissonRx.getMap("myMap");
// 4. Get Redis based implementation of java.util.concurrent.locks.Lock RLock lock = redisson.getLock("myLock"); RLockReactive lockReactive = redissonReactive.getLock("myLock"); RLockRx lockRx = redissonRx.getLock("myLock");
// 4. Get Redis based implementation of java.util.concurrent.ExecutorService RExecutorService executor = redisson.getExecutorService("myExecutorService"); // over 50 Redis based Java objects and services ...
Trending Discussions on helidon
Trending Discussions on helidon
QUESTION
I'm a C developer who needs to create a basic async REST server (synchronous version works fine) in Java using the Microprofile (Helidon MP) framework. Here is my strategy to do this:
The client should do the POST call and provide JSON objects that the POST endpoint will receive. Then, the POST Endpoint method will call a business logic that should do stuff with the received JSON objects. This logic must be run asynchronously. POST should immediately return 202 Accepted. The client should check for async task completion status using a GET request (simple pooling style).
Should POST return a URI that the GET call will use? How? This GET should also provide the percentage of the task completion if the task is in progress. Finally, if the business logic is done, the GET should return the result.
I have a little previous experience with async Java, but no experience with async in this Microprofile/Java EE/Jakarta or whatever it is. I tried several different approaches (AsyncResponse, CompletitionStatus, etc.) to write this code (async POST Method) but nothing seems to be working. The skeleton of the POST functions looks like this:
@Path("/logic")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response logic(JsonObject jsonObject){
BusinessLogic bl = new BusinessLogic();
// This should be done asynchronously.
//How to do it correctly in Microprofile?
bl.doSomethingWithInput(jsonObject);
return Response.status(Response.Status.ACCEPTED).build(); //Return ACCEPTED and the task URI???
}
The GET Handler:
@Path("/logicstatus")
@GET
@@Produces(MediaType.APPLICATION_JSON)
public Response logicStatus(URI as query param???) {
// Magic here?
retrun Response.status(Response.Status.OK).entity(resultJson).build();
}
Thanks a lot. Java reminds me how I love writing device drivers in C :D.
ANSWER
Answered 2021-Dec-23 at 22:10So, first things first. To run things asynchronously Jakarta EE has the annotation @Asynchronous
. So, create a CDI bean with @RequestScoped
, and put there your business method annotated with @Asynchronous
.
Add @ApplicationScoped
CDI annotation to your JAXRS service so you can inject ypur business bean.
Then, for monitoring the task, you have a couple of possibilities.
If you keep the state in a database you just make the
@GET
method to check the state in the database. But I asume this is not your case.If the first approach doesn't fit then you have to keep the state of the different inProgress tasks somehow. I would have another
@ApplicationScoped
CDI bean for that. This would contain aConcurrentHashMap
, with aUUID
as the key, and as the value an Object of your own that contains the current state of any specific async job.
The UUID
has to be generated in the @POST
method, and sent as a parameter to the @Asynchronous
, method. This way the @POST
method can return the UUID
, which will be used then in the @GET
to request the state of the task (querying the @ApplicationScoped
bean).
So the application-wide async tasks state holder should be something like this
@ApplocationScoped
public class AsyncTasksStateHolder {
private Map tasksState = new ConcurrentHashMap<>();
// here go methods to add and get from the map
}
Then, the async business logic may be something like:
@RequestScoped
public class AsyncTaskExecutor {
@Inject
AsyncTasksStateHolder asyncTasksStateHolder;
@Asynchronous
public void doAsyncStuff(UUID uuid, JsonObject jsonObject) {
// create the initial state and save it to asyncTasksStateHolder
// Do your dirty deeds
// Keep updatinf the state in asyncTasksStateHolder
}
}
And now the JAX-RS part:
@Inject
AsyncTasksStateHolder asyncTasksStateHolder
@Inject
AsyncTaskExecutor asyncTasksExecutor;
@Path("/logic")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.TEXT_PLAIN)
public Response logic(JsonObject jsonObject){
UUID uuid = UUID.randomUUID();
asyncTasksExecutor.doAsyncStuff(uuid, jsonObiect); // this returns immediately because of the @Asynchronous
return Response
.status(Response.Status.OK)
.entity(uuid.toString())
.build();
}
@Path("/logicstatus/{uuid}")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response logicStatus(@PathParam("uuid") String uuidAsString) {
// And here you just query the asyncTasksStateHolder
// with the UUID to retreive the state.
}
Some thing to note here:
You will need a mechanism to remove stale state, or the map will grow indefinately.
I used
PLAIN_TEXT
for simplocity, vut feel freento model the@POST
response as you please.Depending on your MicroProfile version you will nees to create the
beans.xml
so CDI gets activated.
And I think that's all. Any problems or doubts do not hesitate to write a comment.
QUESTION
I have a Helidon application and I would like to test (part of) it.
My test is annotated with @HelidonTest
, and now I would like to replace one bean by a mock (and configure this mock, use all other beans as they are found, but with the mock injected).
I did figured out how to:
- Replace one bean by a test implementation (separate class): By annotating the test implementation class with
@Priority(1)
and@Alternative
and supply it by annotating the test with@AddBean(MyBeanTestImpl.class)
.- But I can not create a mock (with Mockito) as an individual class.
- Produce a
mock(MyBean.class)
: By creating a producer method and annotate it with@Produces
:- But it clashes with the real bean and gives: "WELD-001409: Ambiguous dependencies for type..."
- When I annotate it also with
@Alternative
it is simply ignored. - I can not annotate it with
@Priority(1)
, because this annotation can only be applied to types and parameters.
Any idea how I can replace one bean by a mock?
ANSWER
Answered 2021-Dec-16 at 10:19I tried setter injection to manually inject mock beans.
Class under test
@ApplicationScoped
public class SomeService {
private ExternalService externalService;
@Inject
public void setExternalService(ExternalService externalService) {
this.externalService = externalService;
}
public String doSomething() {
return externalService.getData();
}
}
Test Class
@HelidonTest
class SomeServiceTest {
@Inject
private SomeService someService;
private ExternalService externalService;
@BeforeEach
void setUp() {
externalService = Mockito.mock(ExternalService.class);
someService.setExternalService(externalService);
}
@Test
void doSomething() {
Mockito.when(externalService.getData())
.thenReturn("Mock data");
String actual = someService.doSomething();
Assertions.assertEquals("Mock data", actual);
}
}
There are also methods to mock a whole bean by mocking the constructor as well. For that, we have to make use of @Observes annotation
@HelidonTest
public abstract class HelidonTestHelper {
private MockedConstruction mockedConstruction;
void init(@Priority(1) @Observes @Initialized(ApplicationScoped.class) ContainerInitialized containerInitialized) {
mockedConstruction = Mockito.mockConstruction(ExternalService.class);
//mock common beans here. This will be executed once application scope is loaded.
}
void onStop(@Priority(1) @Observes @Destroyed(ApplicationScoped.class) ContainerShutdown containerShutdown) {
//do cleanup here if needed.
mockedConstruction.closeOnDemand();
}
}
Once the above is done, instead of helidon test, you can extend the helper class we created.
class SomeServiceTest extends HelidonTestHelper {
@Inject
private SomeService someService;
@Inject //this will be a mock
private ExternalService externalService;
@Test
void doSomething() {
Mockito.when(externalService.getData())
.thenReturn("Mock data");
String actual = someService.doSomething();
Assertions.assertEquals("Mock data", actual);
}
}
QUESTION
I'd like to set the configuration property org.glassfish.jersey.server.ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE
of Jersey to true
.
I've read the Helidon documentation about configuring the server and tried to add the following to my microprofile-config.properties
:
jersey.config.server.unwrap.completion.stage.writer.enable=true
But it looks like it is not accepted. How do I correctly set a configuration property for Jersey in Helidon MP?
ANSWER
Answered 2021-Nov-15 at 04:24In Helidon MP version 2.4.0, you'll need to follow Jersey's instructions for integrating with MicroProfile Config, bearing in mind that Helidon's MicroProfile Config implementation will already be taken care of so there's no need to duplicate that dependency.
In my opinion Helidon should take care of this for you, but in version 2.4.0 at least it does not.
QUESTION
I would like to server static content from my Helidon MP server. But I only get No handler found for path: /static/index.html
.
I have configured the static resources in src/main/resources/META-INF/microprofile-config.properties
:
server.static.classpath.location=/static
And I start my server with:
Server.builder().config(Config.create()).build().start();
I guess I have to add an JaxRsApplication? But how do I do that?
I figured out it does work when I use the io.helidon.microprofile.cdi.Main
but I want to manually create the server.
ANSWER
Answered 2021-Oct-26 at 23:57This is a config issue, you are using io.helidon.Config.create()
which doesn't support microprofile-config.properties
.
If you use Server.create().start()
, microprofile-config.properties
will work out-of-the-box.
If you want to pass your own instance of config, you can do it like this:
Server.builder().config(ConfigProvider.getConfig()).build().start();
This has the same effect as Server.create()
.
If you want to use the Helidon config API, you can convert an instance of org.eclipse.microprofile.config.Config
to io.helidon.config.Config
like this:
io.helidon.config.mp.MpConfig.toHelidonConfig(ConfigProvider.getConfig())
QUESTION
I am trying to build a huge docker image in an optimized way by applying the principles of incremental building explained here https://www.docker.com/blog/intro-guide-to-dockerfile-best-practices/ .
Unfortunately each time I run the build command docker restarts building the image from scratch, and so I have to download again all the maven dependencies.
Here is the build command:
docker build \
--build-arg MAVEN_SETTINGS_FILE="${HOME}/.m2/settings.xml" \
--build-arg PROJECT_PATH="." \
--file "${DOCKER_FILE}" \
--tag "${IMAGE_TAG}" \
.
and here te Dockerfile
:
# Global vars (for passing between stages)
ARG MAVEN_SETTINGS_FILE
ARG PROJECT_PATH
ARG APP_FOLDER=/app
# 1st stage
FROM maven:3.6-jdk-11 as build
# Build artifact
ARG APP_FOLDER
ENV APP_FOLDER ${APP_FOLDER}
ARG MAVEN_SETTINGS_FILE
ENV MAVEN_SETTINGS_FILE ${MAVEN_SETTINGS_FILE}
ARG PROJECT_PATH
ENV PROJECT_PATH ${PROJECT_PATH}
WORKDIR ${APP_FOLDER}
ADD ${MAVEN_SETTINGS_FILE} .
ADD ${PROJECT_PATH}/pom.xml .
RUN mvn package -s ${MAVEN_SETTINGS_FILE} -DskipTests
ADD ${PROJECT_PATH}/src src
RUN mvn package -s ${MAVEN_SETTINGS_FILE} -DskipTests
# 2nd stage: build image
FROM openjdk:11-jre-slim
ARG APP_FOLDER
ENV APP_FOLDER ${APP_FOLDER}
ENV TARGET_FOLDER ${APP_FOLDER}/target
WORKDIR ${APP_FOLDER}
# Copy the binary built in the 1st stage
COPY --from=build ${TARGET_FOLDER}/myapp-1.0.0-SNAPSHOT.jar .
EXPOSE 8080
CMD ["java", "-jar", "myapp-1.0.0-SNAPSHOT.jar"]
Thank you so much for any suggestion!
Edit 1 (for @sai)Hi @sai, I checked the cached layers by docker history
command and I observed that the MVN steps are missing!
IMAGE CREATED CREATED BY SIZE COMMENT
b78b3d09d314 16 minutes ago /bin/sh -c #(nop) CMD ["java" "-Doracle.jdb… 0B
a2db7da187f0 16 minutes ago /bin/sh -c #(nop) EXPOSE 8080 0B
ed8f3dc45017 16 minutes ago /bin/sh -c #(nop) EXPOSE 8081 0B
715f12eba281 16 minutes ago /bin/sh -c #(nop) COPY dir:33e2303bf32b392fc… 58.3MB
4edb35a1b6f6 16 minutes ago /bin/sh -c #(nop) COPY file:0b42aca8bb0ad316… 234kB
56ecbfb34e74 16 minutes ago /bin/sh -c #(nop) COPY dir:8497884af419f408f… 4.59kB
255913b0fc25 16 minutes ago /bin/sh -c #(nop) WORKDIR /app 0B
87c5b4ca34df 16 minutes ago /bin/sh -c #(nop) ENV TARGET_FOLDER=/app/ta… 0B
5f95ab5b8d19 16 minutes ago /bin/sh -c #(nop) ENV APP_FOLDER=/app 0B
da6d51b1d3b8 16 minutes ago /bin/sh -c #(nop) ARG APP_FOLDER 0B
940f48bb6c92 3 days ago /bin/sh -c set -eux; arch="$(dpkg --print-… 142MB
3 days ago /bin/sh -c #(nop) ENV JAVA_VERSION=11.0.11+9 0B
3 days ago /bin/sh -c #(nop) ENV LANG=C.UTF-8 0B
3 days ago /bin/sh -c #(nop) ENV PATH=/usr/local/openj… 0B
3 days ago /bin/sh -c { echo '#/bin/sh'; echo 'echo "$J… 27B
3 days ago /bin/sh -c #(nop) ENV JAVA_HOME=/usr/local/… 0B
3 days ago /bin/sh -c set -eux; apt-get update; apt-g… 8.82MB
3 days ago /bin/sh -c #(nop) CMD ["bash"] 0B
3 days ago /bin/sh -c #(nop) ADD file:7362e0e50f30ff454… 69.3MB
My opinion is that all the instructions which use a variable to be expanded do not generate a cached layer. Is it right for you too?
Edit 2 (Helidon demo)I tryed to go digger with Helidon demo, and I observed that it does not show in the history the MVN layer. Conversely it uses cached layers.
Look at the docker file and second build execution log:
# 1st stage, build the app
FROM maven:3.6-jdk-11 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:11-jre-slim
WORKDIR /helidon
# Copy the binary built in the 1st stage
COPY --from=build /helidon/target/helidon-quickstart-mp.jar ./
COPY --from=build /helidon/target/libs ./libs
CMD ["java", "-jar", "helidon-quickstart-mp.jar"]
EXPOSE 8080
Sending build context to Docker daemon 43.01kB
Step 1/13 : FROM maven:3.6-jdk-11 as build
---> e23b595c92ad
Step 2/13 : WORKDIR /helidon
---> Using cache
---> 25e45ff1f01d
Step 3/13 : ADD pom.xml .
---> Using cache
---> ec5c0a3ecd2c
Step 4/13 : RUN mvn package -Dmaven.test.skip -Declipselink.weave.skip
---> Using cache
---> a21083c406a0
Step 5/13 : ADD src src
---> Using cache
---> d718f90a4c6d
Step 6/13 : RUN mvn package -DskipTests
---> Using cache
---> ebdb2ff847fd
Step 7/13 : RUN echo "done!"
---> Using cache
---> d9c9f46d0af2
Step 8/13 : FROM openjdk:11-jre-slim
---> 940f48bb6c92
Step 9/13 : WORKDIR /helidon
---> Using cache
---> e0aa150de7c3
Step 10/13 : COPY --from=build /helidon/target/helidon-quickstart-mp.jar ./
---> Using cache
---> 0f64c021b20f
Step 11/13 : COPY --from=build /helidon/target/libs ./libs
---> Using cache
---> d2c6fad54ac1
Step 12/13 : CMD ["java", "-jar", "helidon-quickstart-mp.jar"]
---> Using cache
---> 7de63ada236c
Step 13/13 : EXPOSE 8080
---> Using cache
---> d6a11cd62373
Successfully built d6a11cd62373
Successfully tagged helidon-quickstart-mp:latest
I looked better at my second build execution log and I supposed, the ENV variabiles assignments breaking the caching:
Sending build context to Docker daemon 2.294MB
Step 1/36 : ARG CI_CONTAINER_BUILD_FULL_VERSION
Step 2/36 : ARG CI_CONTAINER_BUILD_PROFILE
Step 3/36 : ARG CI_CONTAINER_BUILD_VERSION
Step 4/36 : ARG CI_CONTAINER_MAVEN_BUILD_OPTIONS
Step 5/36 : ARG CI_CONTAINER_MAVEN_POM_ARTIFACT_ID
Step 6/36 : ARG CI_CONTAINER_MAVEN_POM_GROUP_ID
Step 7/36 : ARG CI_CONTAINER_MAVEN_POM_VERSION
Step 8/36 : ARG CI_CONTAINER_MAVEN_SETTINGS_FILE
Step 9/36 : ARG CI_CONTAINER_PROJECT_PATH
Step 10/36 : ARG APP_FOLDER=/app
Step 11/36 : FROM maven:3.6-jdk-11 as build
---> e23b595c92ad
Step 12/36 : ARG APP_FOLDER
---> Using cache
---> 7418c1e78088
Step 13/36 : ENV APP_FOLDER ${APP_FOLDER}
---> Using cache
---> 9fb55b74b57b
Step 14/36 : ARG CI_CONTAINER_MAVEN_SETTINGS_FILE
---> Using cache
---> 9de7642ea7ae
Step 15/36 : ENV CI_CONTAINER_MAVEN_SETTINGS_FILE ${CI_CONTAINER_MAVEN_SETTINGS_FILE}
---> Running in 0d5655b4dd2b
Removing intermediate container 0d5655b4dd2b
---> d590a3bc4167
Step 16/36 : ARG CI_CONTAINER_MAVEN_BUILD_OPTIONS
---> Running in 528c5d6c82f2
Removing intermediate container 528c5d6c82f2
---> 5ec69a0c4629
Step 17/36 : ENV CI_CONTAINER_MAVEN_BUILD_OPTIONS ${CI_CONTAINER_MAVEN_BUILD_OPTIONS}
---> Running in eefe59ddc94b
Removing intermediate container eefe59ddc94b
---> beb77c7c67e5
Step 18/36 : ARG CI_CONTAINER_PROJECT_PATH
---> Running in da389f2e0824
Removing intermediate container da389f2e0824
---> 6835d33be70e
Step 19/36 : ENV CI_CONTAINER_PROJECT_PATH ${CI_CONTAINER_PROJECT_PATH}
---> Running in 89420b67a110
Removing intermediate container 89420b67a110
---> fd1b05ed1dfd
Step 20/36 : WORKDIR ${APP_FOLDER}
---> Running in 39135509f1d7
Removing intermediate container 39135509f1d7
---> 833258753a45
Step 21/36 : COPY ${CI_CONTAINER_MAVEN_SETTINGS_FILE} .
---> 6f1b6a7176de
Step 22/36 : COPY ${CI_CONTAINER_PROJECT_PATH}/pom.xml .
---> 92f34751c641
Step 23/36 : RUN mvn -e -B -s ${CI_CONTAINER_MAVEN_SETTINGS_FILE} -DskipTests -Dmaven.openapi-generator.skip ${CI_CONTAINER_MAVEN_BUILD_OPTIONS} package
---> Running in 38fcf8af4523
[INFO] Error stacktraces are turned on.
[INFO] Scanning for projects...
[INFO] Downloading from public: http://ci.betting.sisal.it/nexus/repository/maven-public/it/sisal/betting/root-pom/2.0.2/root-pom-2.0.2.pom
[INFO] Downloaded from public: http://ci.betting.sisal.it/nexus/repository/maven-public/it/sisal/betting/root-pom/2.0.2/root-pom-2.0.2.pom (12 kB at 41 kB/s)
[INFO] Downloading from public: http://ci.betting.sisal.it/nexus/repository/maven-public/io/helidon/helidon-dependencies/2.3.0/helidon-dependencies-2.3.0.pom
... and so on...
Now I should know to make variable assignments cacheable!!!
ANSWER
Answered 2021-May-16 at 13:03In the documentation it is mentioned that
Each FROM instruction can use a different base, and each of them begins a new stage of the build
To check what steps are cached, run the following command
docker history
You will only see the instructions from the final build.
QUESTION
I am new to Helidon and i am trying to create a basic CRUD REST service using Helidon SE. I have been referring the DbClient examples in GitHib (https://github.com/oracle/helidon/tree/master/examples/dbclient) to create a basic CRUD REST Service.
I am able to do Read all/one and Delete all/one in DB but unable to do Create or Update Operation, below is the error stack which i get when trying to invoke a POST Service :
java.util.concurrent.ExecutionException: Unhandled 'cause' of this exception encountered.
at io.helidon.webserver.RequestRouting$RoutedRequest.defaultHandler(RequestRouting.java:394)
at io.helidon.webserver.RequestRouting$RoutedRequest.nextNoCheck(RequestRouting.java:374)
at io.helidon.webserver.RequestRouting$RoutedRequest.next(RequestRouting.java:417)
at io.helidon.webserver.Handler.lambda$create$4(Handler.java:99)
at java.base/java.util.concurrent.CompletableFuture.uniExceptionally(CompletableFuture.java:986)
at java.base/java.util.concurrent.CompletableFuture.uniExceptionallyStage(CompletableFuture.java:1004)
at java.base/java.util.concurrent.CompletableFuture.exceptionally(CompletableFuture.java:2307)
at java.base/java.util.concurrent.CompletableFuture.exceptionally(CompletableFuture.java:143)
at io.helidon.common.reactive.CompletionAwaitable.exceptionally(CompletionAwaitable.java:293)
at io.helidon.webserver.Handler.lambda$create$5(Handler.java:97)
at io.helidon.webserver.RequestRouting$RoutedRequest.next(RequestRouting.java:320)
at io.helidon.metrics.MetricsSupport$MetricsContextHandler.accept(MetricsSupport.java:619)
at io.helidon.webserver.RequestRouting$RoutedRequest.next(RequestRouting.java:320)
at io.helidon.metrics.MetricsSupport.lambda$configureVendorMetrics$7(MetricsSupport.java:364)
at io.helidon.webserver.RequestRouting$RoutedRequest.next(RequestRouting.java:320)
at io.helidon.webserver.WebTracingConfig$RequestSpanHandler.accept(WebTracingConfig.java:247)
at io.helidon.webserver.RequestRouting$RoutedRequest.next(RequestRouting.java:320)
at io.helidon.common.context.Contexts.runInContext(Contexts.java:98)
at io.helidon.webserver.RequestRouting.route(RequestRouting.java:87)
at io.helidon.webserver.ForwardingHandler.channelRead0(ForwardingHandler.java:167)
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:311)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:425)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.IllegalStateException: No reader found for type: class io.helidon.examples.quickstart.se.pokemon.Pokemon
at io.helidon.media.common.MessageBodyReaderContext.readerNotFound(MessageBodyReaderContext.java:338)
at io.helidon.media.common.MessageBodyReaderContext.unmarshall(MessageBodyReaderContext.java:167)
at io.helidon.media.common.MessageBodyReadableContent.as(MessageBodyReadableContent.java:117)
at io.helidon.webserver.Handler.lambda$create$5(Handler.java:83)
... 34 more
Below is the code written by
Main.javapackage io.helidon.examples.quickstart.se;
import io.helidon.config.Config;
import io.helidon.config.ConfigValue;
import io.helidon.dbclient.DbClient;
import io.helidon.examples.quickstart.se.pokemon.PokemonService;
import io.helidon.health.HealthSupport;
import io.helidon.health.checks.HealthChecks;
import io.helidon.media.jsonp.JsonpSupport;
import io.helidon.metrics.MetricsSupport;
import io.helidon.webserver.Routing;
import io.helidon.webserver.WebServer;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.logging.LogManager;
/**
* The application main class.
*/
public final class Main {
/**
* Cannot be instantiated.
*/
private Main() {
}
/**
* Application main entry point.
* @param args command line arguments.
* @throws IOException if there are problems reading logging properties
*/
public static void main(final String[] args) throws IOException {
startServer();
}
/**
* Start the server.
* @return the created {@link WebServer} instance
* @throws IOException if there are problems reading logging properties
*/
static WebServer startServer() throws IOException {
// load logging configuration
setupLogging();
System.out.println("Logging Set up");
// By default this will pick up application.yaml from the classpath
Config config = Config.create();
System.out.println("Config created");
// Build server with JSONP support
WebServer server = WebServer.builder(createRouting(config))
.config(config.get("server"))
.addMediaSupport(JsonpSupport.create())
.build();
System.out.println("Webserver Created : "+server);
// Try to start the server. If successful, print some info and arrange to
// print a message at shutdown. If unsuccessful, print the exception.
System.out.println("Server startup initiating");
server.start()
.thenAccept(ws -> {
System.out.println(
"WEB server is up! http://localhost:" + ws.port() + "/greet");
ws.whenShutdown().thenRun(()
-> System.out.println("WEB server is DOWN. Good bye!"));
})
.exceptionally(t -> {
System.err.println("Startup failed: " + t.getMessage());
t.printStackTrace(System.err);
return null;
});
// Server threads are not daemon. No need to block. Just react.
return server;
}
/**
* Creates new {@link Routing}.
*
* @return routing configured with JSON support, a health check, and a service
* @param config configuration of this server
*/
private static Routing createRouting(Config config) {
System.out.println("Inside create Routing.");
Config dbConfig = config.get("db");
System.out.println("dbConfig : ");
System.out.println(dbConfig.get("db.source").asString().orElse("No Data"));
ConfigValue> test = dbConfig.asMap();
// for (Map.Entry entry : test)
// System.out.println("Key = " + entry.getKey() +
// ", Value = " + entry.getValue());
//Client services are added through a service loader
DbClient dbClient = DbClient.builder(dbConfig).build();
System.out.println("dbClient : "+dbClient);
MetricsSupport metrics = MetricsSupport.create();
GreetService greetService = new GreetService(config);
PokemonService pokemonService = new PokemonService(dbClient);
HealthSupport health = HealthSupport.builder()
.addLiveness(HealthChecks.healthChecks()) // Adds a convenient set of checks
.build();
System.out.println("Returning Value");
return Routing.builder()
.register(health) // Health at "/health"
.register(metrics) // Metrics at "/metrics"
.register("/greet", greetService)
.register("/pokemon", pokemonService)
.build();
}
/**
* Configure logging from logging.properties file.
*/
private static void setupLogging() throws IOException {
try (InputStream is = Main.class.getResourceAsStream("/logging.properties")) {
LogManager.getLogManager().readConfiguration(is);
}
}
}
package io.helidon.examples.quickstart.se.pokemon;
import io.helidon.common.http.Http;
import io.helidon.common.reactive.Multi;
import io.helidon.dbclient.DbClient;
import io.helidon.dbclient.DbRow;
import io.helidon.webserver.*;
import javax.json.JsonObject;
import java.util.concurrent.CompletionException;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.logging.Logger;
public class PokemonService implements Service {
private static final Logger LOGGER = Logger.getLogger(PokemonService.class.getName());
private final AtomicReference greeting = new AtomicReference<>();
private final DbClient dbClient;
public PokemonService(DbClient dbClient){
this.dbClient = dbClient;
greeting.set("Hello Pokemon");
}
@Override
public void update(Routing.Rules rules) {
rules
.get("/", this::listPokemons)
// get one
.get("/{name}", this::getPokemon)
// create new
.post("/", Handler.create(Pokemon.class, this::insertPokemon))
// delete all
.delete("/", this::deleteAllPokemons)
// delete one
.delete("/{name}", this::deletePokemon)
;
}
private void listPokemons(ServerRequest request, ServerResponse response) {
Multi rows = dbClient.execute(exec -> exec.namedQuery("select-all"))
.map(it -> it.as(JsonObject.class));
response.send(rows, JsonObject.class);
}
private void insertPokemon(ServerRequest request, ServerResponse response, Pokemon pokemon) {
System.out.println("Start of insertPokemon");
System.out.println("pokemon : ");
System.out.println(pokemon);
System.out.println("Name : "+pokemon.getName());
System.out.println("Type : "+pokemon.getType());
dbClient.execute(exec -> exec
.createNamedInsert("insert2")
.namedParam(pokemon)
.execute())
.thenAccept(count -> response.send("Inserted: " + count + " values"))
.exceptionally(throwable -> sendError(throwable, response));
}
private T sendError(Throwable throwable, ServerResponse response) {
Throwable realCause = throwable;
if (throwable instanceof CompletionException) {
realCause = throwable.getCause();
}
response.status(Http.Status.INTERNAL_SERVER_ERROR_500);
response.send("Failed to process request: " + realCause.getClass().getName() + "(" + realCause.getMessage() + ")");
LOGGER.log(Level.WARNING, "Failed to process request", throwable);
return null;
}
private void getPokemon(ServerRequest request, ServerResponse response) {
String pokemonName = request.path().param("name");
dbClient.execute(exec -> exec.namedGet("select-one", pokemonName))
.thenAccept(opt -> opt.ifPresentOrElse(it -> sendRow(it, response),
() -> sendNotFound(response, "Pokemon "
+ pokemonName
+ " not found")))
.exceptionally(throwable -> sendError(throwable, response));
}
private void sendRow(DbRow row, ServerResponse response) {
response.send(row.as(JsonObject.class));
}
private void sendNotFound(ServerResponse response, String message) {
response.status(Http.Status.NOT_FOUND_404);
response.send(message);
}
private void deleteAllPokemons(ServerRequest request, ServerResponse response) {
dbClient.execute(exec -> exec
// this is to show how ad-hoc statements can be executed (and their naming in Tracing and Metrics)
.createDelete("DELETE FROM pokemons")
.execute())
.thenAccept(count -> response.send("Deleted: " + count + " values"))
.exceptionally(throwable -> sendError(throwable, response));
}
private void deletePokemon(ServerRequest request, ServerResponse response) {
final String name = request.path().param("name");
dbClient.execute(exec -> exec.namedDelete("delete", name))
.thenAccept(count -> response.send("Deleted: " + count + " values"))
.exceptionally(throwable -> sendError(throwable, response));
}
}
package io.helidon.examples.quickstart.se.pokemon;
import io.helidon.common.Reflected;
@Reflected
public class Pokemon {
private String name;
private String type;
/**
* Default constructor.
*/
public Pokemon() {
// JSON-B
}
/**
* Create pokemon with name and type.
*
* @param name name of the beast
* @param type type of the beast
*/
public Pokemon(String name, String type) {
this.name = name;
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
package io.helidon.examples.quickstart.se.pokemon;
import io.helidon.dbclient.DbColumn;
import io.helidon.dbclient.DbMapper;
import io.helidon.dbclient.DbRow;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Maps database statements to {@link io.helidon.examples.quickstart.se.pokemon.Pokemon} class.
*/
public class PokemonMapper implements DbMapper {
@Override
public Pokemon read(DbRow row) {
// DbColumn id = row.column("id");
DbColumn name = row.column("name");
DbColumn type = row.column("type");
return new Pokemon(name.as(String.class), type.as(String.class));
}
@Override
public Map toNamedParameters(Pokemon value) {
Map map = new HashMap<>(2);
// map.put("id", value.getId());
map.put("name", value.getName());
map.put("type", value.getType());
return map;
}
@Override
public List toIndexedParameters(Pokemon value) {
List list = new ArrayList<>(2);
// list.add(value.getId());
list.add(value.getName());
list.add(value.getType());
return list;
}
}
PokemonMapperProvider.java
package io.helidon.examples.quickstart.se.pokemon;
import io.helidon.dbclient.DbMapper;
import io.helidon.dbclient.spi.DbMapperProvider;
import javax.annotation.Priority;
import java.util.Optional;
/**
* Provides pokemon mappers.
*/
@Priority(1000)
public class PokemonMapperProvider implements DbMapperProvider {
private static final PokemonMapper MAPPER = new PokemonMapper();
@SuppressWarnings("unchecked")
@Override
public Optional> mapper(Class type) {
if (type.equals(Pokemon.class)) {
return Optional.of((DbMapper) MAPPER);
}
return Optional.empty();
}
}
Any help in this regard is truly appreciated.
Regards, Gaurav
ANSWER
Answered 2020-Nov-24 at 20:23The Pokemon class is a Java Bean and can be converted from/to JSON with JSON-B; that is what the original example does.
You need to register the Jsonb media support:
.addMediaSupport(JsonbSupport.create())
This also requires the following Maven dependency:
io.helidon.media
helidon-media-jsonb
QUESTION
I'm new to Helidon MP and I'm trying to implement my first microservice. I wasn't able to find out how to debug my application, can someone point me to a good example or documentation? Is there a way to start the runtime in debug mode or something like this?
thanks in advance
ANSWER
Answered 2020-Nov-19 at 21:54Helidon MP is not really a runtime in the sense of being an application server. It's primarily a collection of libraries you add to your project. Therefore you debug programs that use Helidon like you would debug any other Java application, i.e. by adding Java debug switches to the command line.
Here is the output from java -agentlib:jdwp=help
, which should get you started with basic Java debugging:
$ $(/usr/libexec/java_home -v11)/bin/java -agentlib:jdwp=help
Java Debugger JDWP Agent Library
--------------------------------
(see http://java.sun.com/products/jpda for more information)
jdwp usage: java -agentlib:jdwp=[help]|[=, ...]
Option Name and Value Description Default
--------------------- ----------- -------
suspend=y|n wait on startup? y
transport= transport spec none
address= transport spec ""
server=y|n listen for debugger? n
launch= run debugger on event none
onthrow= debug on throw none
onuncaught=y|n debug on any uncaught? n
timeout= for listen/attach in milliseconds n
mutf8=y|n output modified utf-8 n
quiet=y|n control over terminal messages n
Obsolete Options
----------------
strict=y|n
stdalloc=y|n
Examples
--------
- Using sockets connect to a debugger at a specific address:
java -agentlib:jdwp=transport=dt_socket,address=localhost:8000 ...
- Using sockets listen for a debugger to attach:
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y ...
Notes
-----
- A timeout value of 0 (the default) is no timeout.
Warnings
--------
- The older -Xrunjdwp interface can still be used, but will be removed in
a future release, for example:
java -Xdebug -Xrunjdwp:[help]|[=, ...]
QUESTION
I have a small application in Helidon start. It is mostly a REST interface, but I also want to start some background monitoring / logging on startup.
I would like that monitoring to be activated / deactivated by config. The issue I am facing is that the config is not being picked up if my class is instantiated manually.
Here is a very short code snippet :
Starting the application
public class Main {
private Main() { }
public static void main(final String[] args) throws IOException {
Server server = startServer();
CellarMonitoring monitoring = new CellarMonitoring();
monitoring.start();
}
static Server startServer() {
return Server.create().start();
}
}
Starting monitoring or not based on Configuration :
package nl.lengrand.cellar;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
public class CellarMonitoring {
@Inject
@ConfigProperty(name = "monitoring.enabled", defaultValue = "true")
private volatile boolean monitoringEnabled; <= Always false
public void start(){
if(monitoringEnabled) {
System.out.println("Monitoring enabled by config. Starting up");
}
else System.out.println("Monitoring disabled by config");
}
}
This code will always return "Monitoring disabled by config", whatever I do.
Accessing the config directly like described in the documentation is not really an option either since the onStartup
method will never be fired.
What is the proper way to inject a class in my server so it can access the config as desired?
ANSWER
Answered 2020-Nov-13 at 20:57Your question is actually about CDI.
In order for any kind of dependency injection to work with CDI, CDI must instantiate the thing to be injected. In this case, you instantiate the thing to be injected, so CDI never "sees" it, so it is never injected.
I am speculating here, but I'm guessing your use case is really just: "I'd like my CellarMonitoring
component to be notified when CDI comes up. How do I do that?"
There are many answers to that question on this site and elsewhere. Essentially you take advantage of the fact that CDI will fire an event notifying any interested listeners in the initialization of the application scope. The application scope is effectively the lifespan of the application itself, so you can think of it as a startup event.
A full CDI tutorial is beyond the scope of this question and answer, but, to cut to the chase, here's a way to do it. I have had to make various assumptions, such as that you want CellarMonitoring
to be singleton-like:
@ApplicationScoped
public class CellarMonitoring {
@Inject
@ConfigProperty(name = "monitoring.enabled", defaultValue = "true")
private volatile boolean monitoringEnabled; // <= Always false
public void start() {
if (monitoringEnabled) {
System.out.println("Monitoring enabled by config. Starting up");
} else {
System.out.println("Monitoring disabled by config");
}
}
private void onStartup(@Observes @Initialized(ApplicationScoped.class) final Object event) {
// The container has started. You can now do what you want to do.
this.start();
}
}
QUESTION
I am getting the next issue after running:
$ mvn azure-functions:deploy
[ERROR] Failed to execute goal com.microsoft.azure:azure-functions-maven-plugin:1.9.0:deploy (default-cli) on project helidon-examples-microprofile-azure-functions: Your function app artifact compile version is higher than the java version in function host, please downgrade the project compile version and try again. -> [Help 1]
I don't know what does it mean that function host. It suggests to downgrade the compile version (that is currently jdk 11), but I cannot downgrade it because my applications depends on Helidon, and that is supported for JDK 11.
These are the generated files after running mvn package. The lib contains dependencies.
$ ls target/azure-functions/function2-helidon-azure/
helidon-examples-microprofile-azure-functions.jar host.json lib local.settings.json toUpperCase
This is the java version:
$ java -version
openjdk version "11.0.7" 2020-04-14 LTS
OpenJDK Runtime Environment 20.4-(Zulu-11.39+15-linux_x64)-Microsoft-Azure-restricted (build 11.0.7+10-LTS)
OpenJDK 64-Bit Server VM 20.4-(Zulu-11.39+15-linux_x64)-Microsoft-Azure-restricted (build 11.0.7+10-LTS, mixed mode)
These are the JSON files:
host.json
{
"functionTimeout": "00:09:00",
"version": "3.0"
}
local.settings.json
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"AzureWebJobsDashboard": "",
"FUNCTIONS_WORKER_RUNTIME": "java"
}
}
And the pom.xml file is:
4.0.0
io.helidon.applications
helidon-mp
2.0.3-SNAPSHOT
../../../applications/mp/pom.xml
11
function2-helidon-azure
westus
java-function-group
${project.build.directory}/azure-functions/${functionAppName}
1.9.0
1.4.0
helidon-examples-microprofile-azure-functions
Helidon Microprofile Examples Azure Functions
com.microsoft.azure.functions
azure-functions-java-library
${azure.functions.java.library.version}
io.helidon.microprofile.cloud
helidon-microprofile-cloud-azure-functions
org.apache.maven.plugins
maven-clean-plugin
${basedir}
obj/**
${basedir}
extensions.csproj
com.microsoft.azure
azure-functions-maven-plugin
${azure.functions.maven.plugin.version}
org.apache.maven.plugins
maven-deploy-plugin
true
org.apache.maven.plugins
maven-dependency-plugin
copy-dependencies
prepare-package
copy-dependencies
${stagingDirectory}/lib
false
false
true
runtime
azure-functions-java-library
com.microsoft.azure
azure-functions-maven-plugin
${functionResourceGroup}
${functionAppName}
${functionAppRegion}
WEBSITE_RUN_FROM_PACKAGE
1
FUNCTIONS_EXTENSION_VERSION
~3
FUNCTIONS_WORKER_RUNTIME
java
package-functions
package
maven-resources-plugin
copy-resources
package
copy-resources
true
${stagingDirectory}
${project.basedir}/src/main/azure
**
ANSWER
Answered 2020-Oct-13 at 08:58I fixed it following this example: https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-azure-function-azure-cli?pivots=programming-language-java&tabs=bash%2Cbrowser
In azure-functions-maven-plugin I was missing the section under 'configuration':
linux
11
Then there are other issues after that.
I solved adding in the section 'configuration' the next:
java-functions-app-service-plan
And also the value of property 'functionResourceGroup' was misspelled. The value is:
java-functions-group
QUESTION
I have a @ApplicationScoped bean in my Helidon MP microservice, is there a way to force the creation of the bean at server startup instead at first method call?
I need this bean ready and running just after server startup but every attempt I made it's inconclusive
ANSWER
Answered 2020-Jul-17 at 14:00I found a way to solve it. If your bean observes the initialization of ApplicationScoped
it will be instantiated during startup phase. It's a trick but it works fine.
public void init(@Observes @Initialized(ApplicationScoped.class) Object init) {
}
Community Discussions, Code Snippets contain sources that include Stack Exchange Network
Vulnerabilities
No vulnerabilities reported
Install helidon
You need JDK 11+ to build Helidon. You also need Maven. We recommend 3.5 or newer. Building the documentation requires the dot utility from Graphviz. This is included in many Linux distributions. For other platforms see https://www.graphviz.org/. Build scripts are located in etc/scripts. These are primarily used by our pipeline, but a couple are handy to use on your desktop to verify your changes.
copyright.sh: Run a full copyright check
checkstyle.sh: Run a full style check
Support
Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from over 650 million Knowledge Items
Find more librariesExplore Kits - Develop, implement, customize Projects, Custom Functions and Applications with kandi kits
Save this library and start creating your kit
Share this Page