Skip to content
Tim Quinn edited this page May 10, 2024 · 68 revisions

Frequently Asked Questions

Welcome to the Helidon FAQ! If you're reading this, you're a reader, so you might also be interested in our website.

What is this document?

This is a living (somewhat irreverent) document (and Wiki page!) cataloging frequently asked and frequently encountered questions around the Helidon project. It may be updated, edited, reorganized, repaginated, or otherwise generally munged at any time for any reason without prior notice. There may be parts of this document that are incomplete, "to be done", missing, and so on. No guarantees are made about link longevity or content lifespan. We like to keep this document fresh.

How should I read it?

You may read it straight through if you wish, though it has been designed to be deeply linkable. As questions come up, we post deep links to the relevant section in this document in response.

Additionally, since Helidon is (among many other things) a careful mix of our own code and repackaged code, some questions that seem like they concern Helidon are actually questions about its constituent technologies. This document tries to balance giving you a useful answer to a question, while not also, say, rewriting the documentation for Jakarta RESTful Web Services, or CDI, or Netty, or one of the other technologies that help make Helidon work. So some topics you may find here are really better addressed by other documentation sites, and we've tried to link to them as appropriate.

Does it contain all the things I need to know about Helidon?

No, not at all. For that, you want our documentation site.

If this document says X and the website says Y, which is right?

The website.

Are there code samples?

Yes. See below. However, if you're looking for code to copy and paste, you're better served by looking at our examples. (Also: copying and pasting code without understanding what it does is almost always the wrong thing to do. You may notice that most of the examples in this FAQ contain comments designed to make copying and pasting without editing as clumsy and awkward as possible. That's on purpose.)

What is Helidon?

Helidon is a set of Java libraries for writing microservices, oriented around a Netty-based webserver. Helidon comes in two flavors: Helidon SE (reactive and no magic) and Helidon MP (a MicroProfile implementation). It's open source and available under the Apache 2.0 license.

What's the difference between Helidon SE and Helidon MP?

The difference is primarily programming style.

Helidon MP is our implementation of the Eclipse MicroProfile specification. MicroProfile has familiar enterprise Java APIs like Jakarta RESTful Web Services, CDI and JSON-P. MicroProfile also specifies other microservice-focused APIs like MicroProfile Health and MicroProfile Metrics. MicroProfile APIs tend to follow a declarative style with lots of annotations. If you are used to programming in a Jakarta EE- or Spring Boot-like style, then Helidon MP will feel familiar.

Helidon SE is based on our own reactive APIs. It uses a functional style of programming with almost no annotations. You're just calling methods on plain old Java objects (POJOs). No magic!

How do I get started?

See the Getting Started section in our documentation!

What versions of Java, Maven and all the other stuff do I need?

Helidon's prerequisites are available on our documentation site. (They're not written here because then they'd need to be maintained in two places.)

Helidon MP Topics

True MicroProfile Topics (not other topics in disguise)

What version of MicroProfile does Helidon MP support?

Please see the Supported APIs page in our Wiki.

What's the difference between the helidon-microprofile and helidon-microprofile-core dependency bundles?

  • The io.helidon.microprofile.bundles:helidon-microprofile bundle contains support for all of the foundational MicroProfile features. It's handy for getting going quickly and experimenting. It probably includes too much for any given single use case, but it is definitely convenient.
  • The io.helidon.microprofile.bundles:helidon-microprofile-core bundle contains support for minimal MicroProfile features. You then add additional dependencies as you need them. Using this core bundle is recommended for production services because it minimizes dependencies and footprint.

The Helidon MicroProfile Multiple Port Example uses the core bundle.

You can also view the contents of the full bundle to see what you might need to add to the core bundle.

When I run my Helidon MP application it complains about providers missing for authentication, tracing, etc. What's going on?

You are likely using the full helidon-microprofile dependency bundle (see the previous question). That bundle includes Helidon MicroProfile support for most of the MicroProfile features, but not necessarily providers. For example, with tracing you need to add a tracing provider.

On the other hand, if you do not want those features in your application, then you should start with the core dependency bundle and add only what you need. See the previous question.

Jakarta RESTful Web Services-, Servlet- and Web-Related Topics

What version of Servlet does Helidon MP support?

Helidon MP is not a Servlet implementation, nor does it supply one, so the answer is none. This is deliberate.

How do I get an HttpServletRequest then?

You can't.

But I need headers, or something else that the HttpServletRequest class makes available!

The short answer is: almost certainly Jakarta RESTful Web Services has an analogous object that will do what you want instead.

Helidon MP is a MicroProfile implementation, which means by definition that it is also a Jakarta RESTful Web Services implementation (formerly JAX-RS)—it packages Jersey. By the time you're talking about requests and responses, you are "in" Jersey, and so you do things the Jersey way; Helidon MP is waiting for your response so it can route it back "through" the webserver and over the wire back to the user. But "inside" Jakarta RESTful Web Services constructs—resource classes, filters—loosely speaking there's very little Helidon MP to see. And no Servlet.

So then: most, if not all, of the things you can do with an HttpServletRequest you can do with equivalent Jakarta RESTful Web Services constructs. For example, you can @Inject an instance of HttpHeaders to get the HTTP headers you need.

Similar useful classes include:

These are arbitrary examples and there are others; a full Jakarta RESTful Web Services tutorial is beyond the scope of this document. You may wish to consult the specification.

How do I do {web-related thing} using Helidon MP?

Most of the time, this is not a Helidon MP question.

This category of question reduces to: "How do I do {web thing} in Jakarta RESTful Web Services/Jersey?"

How do I use Jackson in Helidon MP?

(Strictly speaking, this is not a Helidon MP question.)

This question is really: "How do I use Jackson in Jersey?"

How do I use Jackson in Jersey?

As you might expect, the Jersey documentation has the answer.

If you are using Helidon's MicroProfile "bundles" dependency, you'll probably need to exclude some stuff too:

<dependency>
    <groupId>io.helidon.microprofile.bundles</groupId>
    <artifactId>helidon-microprofile</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-binding</artifactId>
        </exclusion>
        <exclusion>
            <groupId>jakarta.json.bind</groupId>
            <artifactId>jakarta.json.bind-api</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.eclipse</groupId>
            <artifactId>yasson</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
</dependency>
Aha! I gotcha! That was Helidon MP-specific!

Yes and no. You'll note that if you had to do all that, it's because you chose to import one of our opinionated bundles, rather than selecting your dependencies individually according to your preferences.

I've added a JAX-RS ExceptionMapper and now my health and metrics endpoints don't work! Why?

If you add a JAX-RS exception mapper that re-maps all exceptions then you can disrupt the integration of Jersey (the JAX-RS implementation) and Helidon. For details see 7959

CDI-Related Topics

How do I make a class a CDI bean?

(Strictly speaking, this is not a Helidon MP question. This is a CDI question.)

You'll need to do a few things.

  1. First, verify that you have a src/main/resources/META-INF/beans.xml file (or src/test/resources/META-INF/beans.xml, or both). A META-INF/beans.xml classpath resource marks that classpath root (usually a jar file) as a bean archive. CDI over the years and versions has changed the micro-level details of exactly what this file means and what its presence and absence mean, but it's best to have one. Now every Java class that ends up under this classpath root (which usually ends up being target/classes or target/test-classes in a Maven project after compilation) will be potentially discoverable in one way or another as a CDI bean.

    1. You'll need to make sure any dependencies you inject also live in a bean archive on your classpath (or are made visible to CDI using other mechanisms, such as portable extensions).
  2. Second, make sure that beans.xml file looks like the following. If you're new to CDI and don't understand what you're doing, then make sure it looks exactly like the following:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
                               https://jakarta.ee/xml/ns/jakartaee/beans_3_0.xsd"
           version="3.0"
           bean-discovery-mode="annotated">
      <!--
           This file was copied verbatim from the Helidon MP FAQ.
           You should probably look at it carefully to make sure it
           meets your needs and then remove this comment.
      -->
    </beans>

    Note in particular the bean-discovery-mode of annotated. You can read more about bean discovery modes in the CDI specification. If you are new to CDI, please leave this as annotated.

  3. Because you've now told CDI that it should discover only annotated beans, you need to place a bean-defining annotation on your class (that is under the classpath root that features META-INF/beans.xml, so usually src/main/java/your/package/here/YourClass.class). There are several bean-defining annotations but the easiest thing to do is assign your bean a scope. (If you don't know what a scope is, then this FAQ has to stop somewhere, so go read about scopes and CDI in general.)

Congratulations; you've made a CDI bean.

Can you give me an example?

Assuming src/main/resources/META-INF/beans.xml is in place with a bean-discovery-mode of annotated, here is an example class that is in the @Dependent scope that is, by virtue of being annotated with @Dependent—a bean-defining annotation—a CDI bean:

@Dependent
public class ThisClassIsAnExampleFromTheHelidonMPFAQ {
  public ThisClassIsAnExampleFromTheHelidonMPFAQ() {
    super();
  }
}

How do I run some code when Helidon MP starts?

Helidon MP is fundamentally a CDI container. So the question is really, "How do I run some code when a CDI container starts?"

How do I run some code when a CDI container starts?

(Strictly speaking, this is not a Helidon MP question.)

You write a particular kind of observer method in an enabled CDI managed bean somewhere that observes the initialization of the application scope.

The method can be named anything you like, can be public, package-protected, protected or private, returns void, and must take at least one parameter that is annotated with @Observes @Initialized(ApplicationScoped.class). (Usually this parameter is simply an Object that you can simply ignore since the specification does not mandate what it must be.) Any other parameter is treated as an injection point, so you can also receive dependencies this way for your method to work with.

Can you give me an example?

Here is an application scope initialization observer method. Remember, it must be declared in a class that is an enabled CDI managed bean:

private void thisIsAnExampleMethodFromTheHelidonMPFAQ(@Observes @Initialized(ApplicationScoped.class) final Object ignoredEvent) {
  // code you put here will be invoked when the CDI container starts, more specifically
  // when CDI's application scope is initialized
}

How do I tell CDI to log things?

(Strictly speaking, this is not a Helidon MP question. This is a CDI question.)

Also strictly speaking, you tell an implementation of CDI to log things (CDI is a specification). Helidon MP uses Weld as its CDI implementation.

OK, how do I tell Weld to log things?

Using Java logging, set the org.jboss.weld level to FINE:

org.jboss.weld.level = FINE

DataSource- and Connection Pool-Related Topics

What connection pools does Helidon MP support?

Helidon MP has support for two different connection pools:

  1. Oracle's Universal Connection Pool
  2. HikariCP

You choose one of them, never both.

What Maven dependencies do I need to use a connection pool?

Universal Connection Pool Maven dependencies

To use the Universal Connection Pool, ensure the following dependency is in your project's pom.xml's <dependencies> stanza:

<dependency>
  <groupId>io.helidon.integrations.cdi</groupId>
  <artifactId>helidon-integrations-cdi-datasource-ucp</artifactId>
  <!-- 
       It's actually best to manage this with Maven's <dependencyManagement> feature.
       If you opt for the explicit version here, always check
       https://search.maven.org/classic/#search%7Cga%7C1%7Chelidon for up-to-date
       available versions.
  -->
  <!-- <version>2.4.0</version> -->
  <scope>runtime</scope>
</dependency>

HikariCP connection pool Maven dependencies

To use the HikariCP connection pool, ensure the following dependency is in your project's pom.xml's <dependencies> stanza:

<dependency>
  <groupId>io.helidon.integrations.cdi</groupId>
  <artifactId>helidon-integrations-cdi-datasource-hikaricp</artifactId>
  <!-- 
       It's actually best to manage this with Maven's <dependencyManagement> feature.
       If you opt for the explicit version here, always check
       https://search.maven.org/classic/#search%7Cga%7C1%7Chelidon for up-to-date
       available versions.
  -->
  <!-- <version>2.4.0</version> -->
  <scope>runtime</scope>
</dependency>

Once I've put my connection pool dependencies in Maven, what else do I need?

To use connection pool-managed DataSource instances in your code, you'll also need Maven dependencies corresponding to your database vendor's JDBC database driver. You can use any JDBC driver dependencies you like. Here are two arbitrary examples.

Oracle JDBC driver dependencies

The Oracle Database JDBC driver is available on Maven Central and comes in a variety of flavors for a variety of use cases, all of which are documented, with examples, in the Developers Guide For Oracle JDBC 21c on Maven Central.

Some of the documented use cases include the Universal Connection Pool. You want to avoid those use cases since the Universal Connection Pool integration provided by Helidon already includes it.

Can you give me an example?

Please read Developers Guide For Oracle JDBC 21c on Maven Central and understand it.

As it spells out in detail, to add just the Oracle Database 21c production JDBC driver to your project, put the following in your project's pom.xml's <dependencies> stanza, if it is not already there or inherited:

<dependencies>
  <dependency>
    <!--
         See
         https://www.oracle.com/database/technologies/maven-central-guide.html
         for more details.
     -->
    <groupId>com.oracle.database.jdbc</groupId>
    <!--
         Why ojdbc*11*? Why not ojdbc*something else*? Because:
         (a) Helidon targets Java 17
         (b) Java 17 "includes" JDBC 4.3, not JDBC 4.2
         (c) ojdbc11 "includes" JDBC 4.3
         (d) ojdbc8 only "includes" JDBC 4.2
         Please see
         https://www.oracle.com/database/technologies/maven-central-guide.html
         for more details.
    -->
    <artifactId>ojdbc11</artifactId>
    <!-- 
       It's actually best to manage this with Maven's <dependencyManagement> feature.
       If you opt for the explicit version here, always check
       https://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22com.oracle.database.jdbc%22
       for up-to-date available versions, and see
       https://www.oracle.com/database/technologies/maven-central-guide.html
       for extremely important information.
    -->
    <!-- <version>21.3.0.0</version> -->
    <scope>runtime</scope>
  </dependency>
</dependencies>

This is only one of several possible use cases you may have and so is not universally suitable.

H2 JDBC driver dependencies

The H2 database is a simple database often used for unit testing.

Can you give me an example?

To add the H2 JDBC driver to your project, put the following in your project's pom.xml's <dependencies> stanza, if it is not already there or inherited:

<dependency>
  <groupId>com.h2database</groupId>
  <artifactId>h2</artifactId>
  <!-- 
       It's actually best to manage this with Maven's <dependencyManagement> feature.
       If you opt for the explicit version here, always check
       https://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22com.h2database%22%20AND%20a%3A%22h2%22
       for up-to-date available versions.
  -->
  <!-- <version>2.0.202</version> -->
  <scope>runtime</scope>
</dependency>

How can I configure a DataSource?

You configure a DataSource in Helidon MP like you configure everything else: using Helidon's built-in MicroProfile Config implementation.

The general pattern is to tell Helidon that you have a named javax.sql.DataSource instance you'd like to set up. Because Helidon MP uses MicroProfile Config as its configuration system, you can put this information in a variety of places.

Setting up a javax.sql.DataSource named yourDataSourceName isn't really different from the general process setting up other types of Java objects with names. For this reason, the general naming pattern Helidon integrations use is fully.qualified.java.class.name. followed by theNameYouChoose. followed by whateverTheActualPropertyIs. So for various javax.sql.DataSource configuration properties for a data source named yourDataSourceName, the properties would all start with javax.sql.DataSource.yourDataSourceName..

Where can I put these properties?

As mentioned, the canonical answer is in the MicroProfile Config specification. Here are just some of the places you can place configuration information.

META-INF/microprofile-config.properties classpath resource

Here's how it might look in the src/main/resources/META-INF/microprofile-config.properties configuration source:

javax.sql.DataSource.yourDataSourceName.somePropertyOfYourConnectionPoolAndDataSource = itsValue
javax.sql.DataSource.yourDataSourceName.someOtherPropertyOfYourConnectionPoolAndDataSource = anotherValue
System properties on the java command line

Here's how it might look as system properties instead:

java \
  -Djavax.sql.DataSource.yourDataSourceName.somePropertyOfYourConnectionPoolAndDataSource=itsValue \
  -Djavax.sql.DataSource.yourDataSourceName.someOtherPropertyOfYourConnectionPoolAndDataSource=anotherValue \
  # ...
Environment variables for your java executable set by your shell

Here's how it might look as environment variables as typed directly into a command line shell, taking advantage of MicroProfile Config's mapping rules, since many shells will not understand environment variable names with periods (.) in them:

JAVAX_SQL_DATASOURCE_YOURDATASOURCENAME_SOMEPROPERTYOFYOURCONNECTIONPOOLANDDATASOURCE=itsValue \
JAVAX_SQL_DATASOURCE_YOURDATASOURCENAME_SOMEOTHERPROPERTYOFYOURCONNECTIONPOOLANDDATASOURCE=anotherValue \
java # ...
Environment variables for your java executable set by the env shell command

Here's how it might look as environment variables as supplied via the env shell command, thus removing the need for MicroProfile Config's mapping rules and making things more efficient as a result:

env 'javax.sql.DataSource.yourDataSourceName.somePropertyOfYourConnectionPoolAndDataSource=itsValue' \
  'javax.sql.DataSource.yourDataSourceName.someOtherPropertyOfYourConnectionPoolAndDataSource=anotherValue' \
  java # ...
application.yaml classpath resources

Here's how it might look as YAML in a src/main/resources/application.yaml file (assuming the file is registered as a MicroProfile Config configuration source):

javax:
  sql:
    DataSource:
      yourDataSourceName:
        somePropertyOfYourConnectionPoolAndDataSource: itsValue
        someOtherPropertyOfYourConnectionPoolAndDataSource: anotherValue
Mix and match

Finally of course you can mix and match these approaches, taking advantage of MicroProfile Config's non-deterministic precedence rules, so that, for example, a data source property set as a system property will override one that may appear in src/main/resources/META-INF/microprofile-config.properties. There is nothing specific to data sources about how all this works.

For more on MicroProfile Config configuration sources, please see the relevant Helidon guide and/or the MicroProfile Config documentation.

Do you support Spring Boot configuration conventions out of the box?

No. Specifically, Helidon does not support application.properties out of the box as a source of external configuration. You can, of course, register a configuration source following the rules of the MicroProfile Config specification.

Can you give me a general example?

Not really. The actual property names are those your DataSource implementation actually supports, and can also vary depending on which connection pool you are using. You'll need to consult the specific examples below tailored to a combination of database driver and connection pool.

Can you give me a specific example of connecting to an Oracle database with a UCP-managed DataSource?

This example presumes that you have set up the Universal Connection Pool as described earlier in this document.

Here is an example in Java properties file format that configures a Universal Connection Pool-managed data source named main to connect to an Oracle Database on localhost port 1521 using the "thin" driver with a service name of XE with a user of scott and a password of tiger:

# (Why "connectionFactoryClassName"? See
# https://docs.oracle.com/en/database/oracle/oracle-database/21/jjuar/oracle/ucp/jdbc/PoolDataSourceImpl.html#setConnectionFactoryClassName_java_lang_String_)
javax.sql.DataSource.main.connectionFactoryClassName = oracle.jdbc.pool.OracleDataSource
javax.sql.DataSource.main.url = jdbc:oracle:thin://@localhost:1521/XE # see https://docs.oracle.com/en/database/oracle/oracle-database/21/jjdbc/data-sources-and-URLs.html#GUID-EF07727C-50AB-4DCE-8EDC-57F0927FF61A
javax.sql.DataSource.main.user = scott
javax.sql.DataSource.main.password = tiger
Can you give me a specific example of connecting to an H2 database with a HikariCP-managed DataSource?

This example presumes that you have set up the HikariCP connection pool as described earlier in this document.

Here is an example that configures a HikariCP-managed data source named test to connect to an in-memory H2 database named unit-testing with a user of sa and an empty password:

# Why "dataSourceClassName"? See
# https://github.com/brettwooldridge/HikariCP#essentials
javax.sql.DataSource.test.dataSourceClassName = org.h2.jdbcx.JdbcDataSource
# Why "dataSource."? See
# https://github.com/brettwooldridge/HikariCP/blob/HikariCP-5.0.0/src/main/java/com/zaxxer/hikari/util/PropertyElf.java#L47-L49
javax.sql.DataSource.test.dataSource.url = jdbc:h2:mem:unit-testing;DB_CLOSE_DELAY=-1 # see http://www.h2database.com/html/features.html#database_url
javax.sql.DataSource.test.dataSource.user = sa
javax.sql.DataSource.test.dataSource.password =
Is there a general pattern I can use to figure out how to set other properties on the Universal Connection Pool in particular?

Yes, but with some limitations and a number of problems.

The Universal Connection Pool exposes various properties as Java Bean properties. In general, if its pooling mechanism, the oracle.ucp.jdbc.PoolDataSourceImpl class (not to be confused with your DataSource implementation that it wraps!), has a public method that starts with set and takes a single String or int parameter (and a corresponding get-prefixed method that returns a value of the same type), you can cause that "setter" method to be invoked by setting an analogous property in your configuration.

For example, to cause the setMinPoolSize(int) method to be called (corresponding to the Java Beans property named minPoolSize), you can set the minPoolSize property for your named data source like so:

javax.sql.DataSource.main.minPoolSize = 1 # for example

One thing that can be confusing when using the Universal Connection Pool in particular is that the DataSource implementation it uses—oracle.ucp.jdbc.PoolDataSourceImpl—to wrap your DataSource implementation (to provide pooling machinery for it)—say, org.h2.jdbcx.JdbcDataSource—exposes some Java Beans properties that are destined both for your DataSource implementation and itself! (The description Java Bean property of oracle.ucp.jdbc.PoolDataSourceImpl is one such example: setting javax.sql.DataSource.yourDataSourceName.description = someDescription will cause the setDescription method of oracle.ucp.jdbc.PoolDataSourceImpl to be called, as well as the setDescription method of org.h2.jdbcx.JdbcDataSource.) Is this confusing? You bet! But it's entirely out of Helidon's control.

It is thus unavoidably hard to figure out which properties affect the pool itself, which affect your DataSource implementation (that the pool wraps), and which might affect both. So, for example, if you were to set the databaseName Java Beans property on the pool, it might also "forward" that to your DataSource implementation (if it supports that Java Bean property). But other Java Bean properties like, for example, maxIdleTime, are (one hopes!) properties of just the connection pooling mechanism itself, and (probably!) not of your DataSource implementation. Unfortunately, knowing which is which basically comes down to intuition, trial, and error.

Is there a general pattern I can use to figure out how to set other properties on the HikariCP connection pool in particular?

Yes. The HikariCP connection pool uses properties that are fully documented. Helidon's integration of the HikariCP connection pool prefixes these properties with its usual type-of-object string (javax.sql.DataSource.), followed by the name of your data source (yourDataSourceName.). So, for example, to set the HikariCP connection pool dataSourceClassName Java Bean property, you would set a corresponding MicroProfile Config property like so:

javax.sql.DataSource.yourDataSourceName.dataSourceClassName = org.h2.jdbcx.JdbcDataSource # for example

To set a Java Bean property on your DataSource implementation itself (for example, the loginTimeout Java Bean property of org.h2.jdbcx.JdbcDataSource), you prefix the property name with the usual Helidon prefix (javax.sql.DataSource.yourDataSourceName.), the HikariCP-reserved word dataSource., and the property name itself (loginTimeout):

javax.sql.DataSource.yourDataSourceName.dataSource.loginTimeout = 100 # for example

What value should I use for my connection pool's property that designates my DataSource class name?

Database Vendor DataSource class name UCP property example HikariCP property example
Oracle oracle.jdbc.pool.OracleDataSource javax.sql.DataSource.yourDataSourceName.connectionFactoryClassName = oracle.jdbc.pool.OracleDataSource javax.sql.DataSource.yourDataSourceName.dataSourceClassName = oracle.jdbc.pool.OracleDataSource
H2 org.h2.jdbcx.JdbcDataSource javax.sql.DataSource.yourDataSourceName.connectionFactoryClassName = org.h2.jdbcx.JdbcDataSource javax.sql.DataSource.yourDataSourceName.dataSourceClassName = org.h2.jdbcx.JdbcDataSource
PostgreSQL org.postgresql.ds.PGSimpleDataSource javax.sql.DataSource.yourDataSourceName.connectionFactoryClassName = org.postgresql.ds.PGSimpleDataSource javax.sql.DataSource.yourDataSourceName.dataSourceClassName = org.postgresql.ds.PGSimpleDataSource

JTA-Related Topics

My transaction is timing out. How can I increase the transaction timeout?

Helidon's JTA support is provided by Narayana. Setting Narayana's properties can be tricky.

To change the default transaction timeout by setting a system property, add this to your java command line:

# Specifies the default timeout for Narayana's transaction coordinator in seconds.
-Dcom.arjuna.ats.arjuna.coordinator.defaultTimeout=120

Thanks! I'm happy my transaction is taking so long that I have to increase the timeout.

You probably shouldn't be. Usually this means you haven't added the right indices to your database tables, or that your JPA query is manifesting the n + 1 problem. In any event, increasing the transaction timeout is almost always the wrong thing to do.

JPA-Related Topics

My persistence.xml has <property name="javax.persistence.jdbc.driver">

Stop right there. This is not a Helidon question. This is a question about application-managed JPA versus container-managed JPA. Helidon provides container-managed JPA integration, which means among many, many other things you don't specify JDBC information in your META-INF/persistence.xml file. You will want to read the specification for more details. Briefly, the entire point of container-managed JPA is that all of this stuff is taken care of for you, so your META-INF/persistence.xml classpath resource should mention a JTA-enabled data source name that should be used to connect to the database. See the other topics in this FAQ concerning data sources for some more information.

Webclient-related Topics

WebClient is the HTTP client of Helidon SE. It is also used internally by other Helidon modules such as the OIDC and the IDCS Roles Security Providers. For more details about WebClient, please refer to the Helidon WebClient Documentation.

Failure when using Proxy

When you set a proxy in WebClient, it will use absolute URI in the request because of changes made in Helidon Issue #2302 and Issue #3438. The use of absolute URI was implemented because of section 5.1.2 Request-URI in https://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html which states:

The absoluteURI form is REQUIRED when the request is being made to a proxy.

The problem is that some hosts have issue processing a request with absolute URI as they expect relative URI instead. As an example, this was encountered when running the testcase in Helidon Issue #4644 where the WebClient is connecting to KeyCloak as an OIDC server via a Proxy. Every time the request is made, KeyCloak will fail with an Http Status 404 response because it cannot handle the absoluteURI.

To resolve this issue, there is a WebClient method called relative-uris(boolean) that can force the request URI to use the relative form rather than absolute and is demonstrated by below source code example:

        Proxy proxy = Proxy.builder()
                .host("localhost")
                .port(8080)
                .build();
        WebClientConfiguration webConfig = WebClient.builder()
                .relativeUris(true)
                .proxy(proxy)
                .configuration();

As noted above, Helidon modules like (https://helidon.io/docs/v3/#/mp/security/providers#OIDC-Provider) and the IDCS Roles security providers use WebClient internally to communicate with the target server. In Helidon MP, there is a special configuration property called relative-uris for OidcConfig that is used for this purpose. Hence if Proxy is needed for either or both modules, relative-uris can be set in the Helidon ConfigSource (such as microprofile-config.properties) like below:

security:
  providers:
    - oidc:
        ...
        force-https-redirects: true
        proxy-host: "www.proxyhost.com"
        proxy-port: 80
        relative-uris: true
    - idcs-role-mapper:
        multitenant: false
        oidc-config:
          ...
          force-https-redirects: true
          proxy-host: "www.proxyhost.com"
          proxy-port: 80
          relative-uris: true

For more details on the Configuration Options for OIDC and IDCS Roles security providers, they can be found in the Helidon documentation under this section and here, respectively.

OpenAPI-related Topics

OpenAPI is the follow-on standard to Swagger for defining the external interface to REST services. MicroProfile OpenAPI supports OpenAPI via MP annotations, additional APIs, and the /openapi endpoint which serves the OpenAPI document for the service.

How do I add OpenAPI support to my Helidon application?

  1. Read our MP OpenAPI documentation here and SE doc here.
  2. Do what the doc says: update your pom.xml and:
    1. Add some annotations to your MP app, or

    2. Choose a way to provide the OpenAPI information to Helidon for your SE app.

      Unlike with MP, which uses annotation processing to find out for itself about your service's endpoints, you have to tell Helidon SE OpenAPI about your service's REST API. The documentation explains how you can do this either by providing a static OpenAPI file or by writing some code that creates the in-memory model for your API.

OpenAPI-based code generation

What is it?

The OpenAPITools project offers a code generator for many languages and platforms. The Helidon team has contributed significant upgrades to the Helidon support in the tool.

How do I use it?

See our documentation for full details:

Generating the OpenAPI document for an app at build time

As described above, Helidon can create an OpenAPI document that describes your application as your service starts up.

If you want to generate the document when you build your application, you can try this plug-in from SmallRye. The Helidon team neither supports nor endorses this plug-in but it might work for you.

The OpenAPI UI

What is it?

SmallRye provides a component you can add to your application so it displays a UI based on the OpenAPI document for your service. You can drive the public API of your service using the UI to make sure your service works as you expect.

How to I add it?

See our updated documentation:

CORS topics

Using CORS properly

Please read the documentation--CORS for MP or CORS for SE--very carefully. It describes how to plan the CORS behavior you want and how to use both the @CrossOrigin annotation (MP only) and configuration (MP and SE) to set up that CORS behavior.

General debugging advice (SE and MP)

  1. Whether you use annotations (in MP) or configuration (MP and SE), you set up CORS behavior by resource, or put another way, by path. Not by Java method. In MP you use the @CrossOrigin annotation on the @OPTIONS methods, but that annotation's settings applies to all methods which share the same @Path, whether explicit or by default.

  2. If you are not seeing the CORS behavior you expect:

    1. Turn on CORS logging:

      io.helidon.webserver.cors.level=FINE

      io.helidon.cors.level=FINE

      Use FINER for a bit more output.

    2. Restart the server.

    3. If you can, send a single problematic request to the server.

    4. Search the log file for relevant messages. For example, if requests you think should work are being refused, search for "CORS denying request" in the log output and read that entire message carefully.

    FINE-level logging produces lots of output (which is why you want to send only one request if you can to debug the problem) but Helidon will explain the decisions it makes about CORS processing for each request.

    In particular, Helidon announces the CORS type of each request: normal, CORS or CORS pre-flight. For each CORS or CORS pre-flight request, Helidon searches for matching CORS settings from your annotations (MP only) or configuration. If no CORS settings apply to the request Helidon reports "CORS denying request" and dumps the request's CORS-related metadata (path, HTTP method, and headers) and then explains why it denied access.

  3. For even more detail, set the logging level to FINER. Internally, Helidon builds a table of CORS setting instances, basically one row for each CORS annotation or CORS config entry you use. FINER-level logging tells you, for each incoming request, which of those CORS settings Helidon matched to the request. Knowing this can sometimes help you understand why CORS treats a request the way it does.

Metrics Topics

Where are the metric types ConcurrentGauge, Meter, and SimpleTimer in Helidon 4?

These types are no longer supported.

Background

Helidon MP 4 implements release 5.0 of the MicroProfile Metrics spec (Ideally, you have read it and the other relevant newer MicroProfile specs as you have planned your migration from Helidon MP 3 to 4.) The Changes in 5.0 section of the MP metrics spec describes the many changes from previous releases of the spec, including the removal of these metric types, and the migration hints section gives some advice in dealing with metric types that are no longer supported.

Helidon SE 4 introduces a neutral Helidon metrics API. (Past releases used the MicroProfile Metrics API.) The neutral API exposes counters, distribution summaries (histograms), gauges, and timers. No concurrent gauges, no meters, no simple timers.

Why the changes?

The trend in the metrics space for quite some time has been away from doing complicated computations at the point of collection (e.g. in a server) toward relying instead on back-ends such as Grafana or Prometheus to derive time series, statistics, etc. The now-retired Meter metric type is a prime example. Not only does this more minimalist approach simplify the work a server has to do (thereby allowing it to run faster), but it also allows the back-ends to aggregate data from multiple servers into useful collections. For example, it’s not mathematically sound to add together or average the one-minute-rate values exposed by the old Meter metric from different server instances even if they measure the same quantity (such as request arrival rates). But if your server instances expose a count of the total number of incoming requests since start-up, then the back-ends can combine count values from different server instances, compute arrival rates for an individual server or derive an aggregate arrival rate across several server instances, etc. All while freeing the servers themselves from doing costly calculations to keep such statistics themselves.

The newer MicroProfile Metrics API and the neutral Helidon API both reflect this trend.

How do I migrate?

Here is a quick summary of what you might do to migrate from the discontinued meter types. (See also the migration hints section of the MP metrics spec mentioned above.)

  • ConcurrentGauge

    Use a Gauge.

  • Meter

    Use a Counter and rely on back ends such as Grafana or Prometheus to compute rates.

  • SimpleTimer

    Use a Timer

Why can't I register the same metric name twice with different tag names in Helidon 4 as I used to?

You can...in Helidon 4 SE. But Helidon 4 MP implements the MicroProfile Metrics 5.0 spec which mandates that all metrics that have the same name must also have the same set of tag names. Those multiple metrics would have different tag values but they must share a consistent tag name set.

Non-Helidon Topics That Nevertheless Come Up A Lot

Maven Topics

I Get A NoClassDefFoundError And—

This is a dependency problem in your project. Depending on the class that was not found at runtime, you need to figure out which of your dependencies is at fault. StackOverflow can help you here. Sometimes you can accidentally include an older version of a dependency that Helidon itself uses. If you've gummed up the Maven works in this way, you'll want to run mvn dependency:tree on your project to find how your dependency is being pulled in (or why it's missing). The Maven documentation has several examples.

We Were Using Helidon 2.x And Upgraded To Helidon 3.x And Now It's Not Working In Some Bizarre Way Involving Missing Classes Or Something

Helidon is just fine. Your project's dependency tree, however, is not.

Almost certainly this is because of the great javax-to-jakarta switchover, which occurred as part of Jakarta EE's evolution from Jakarta EE 8 to Jakarta EE 9. Helidon 2.x implements parts of Jakarta EE 8, so uses Jakarta EE 8 dependencies; Helidon 3.x implements those parts of Jakarta EE 9 instead, so uses Jakarta EE 9 dependencies. Therefore, your whole stack must also switch from Jakarta EE 8 classes to Jakarta EE 9 classes. You can use mvn dependency:tree on your project to find how a particular dependency is being pulled in (or why it's missing). The Maven documentation has several examples.

Is That It?

No. This is just where this document currently ends. Enjoy your day!

Clone this wiki locally