5

I used the Plain Java starter app from the Hello World Starters page of downloads.

I updated its Maven POM to the latest versions of dependencies. So Vaadin 23.3.1, Java 19, jetty-maven-plugin 10.0.12, and so on. The POM looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0"
         xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>project-base</artifactId>
    <name>Project base for Vaadin</name>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>19</maven.compiler.source>
        <maven.compiler.target>19</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <failOnMissingWebXml>false</failOnMissingWebXml>

        <vaadin.version>23.3.1</vaadin.version>
        <drivers.downloader.phase>pre-integration-test</drivers.downloader.phase>
    </properties>

    <repositories>
        <!-- The order of definitions matters. Explicitly defining central here to make sure it has the highest priority. -->
        <repository>
            <id>central</id>
            <url>https://repo.maven.apache.org/maven2</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>vaadin-prereleases</id>
            <url>
                https://maven.vaadin.com/vaadin-prereleases/
            </url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <!-- Repository used by many Vaadin add-ons -->
        <repository>
            <id>Vaadin Directory</id>
            <url>https://maven.vaadin.com/vaadin-addons</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

    <pluginRepositories>
        <!-- The order of definitions matters. Explicitly defining central here to make sure it has the highest priority. -->
        <pluginRepository>
            <id>central</id>
            <url>https://repo.maven.apache.org/maven2</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
        <pluginRepository>
            <id>vaadin-prereleases</id>
            <url>
                https://maven.vaadin.com/vaadin-prereleases/
            </url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.vaadin</groupId>
                <artifactId>vaadin-bom</artifactId>
                <type>pom</type>
                <scope>import</scope>
                <version>${vaadin.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>com.vaadin</groupId>
            <!-- Replace artifactId with vaadin-core to use only free components -->
            <artifactId>vaadin</artifactId>
        </dependency>

        <!-- Added to provide logging output as Vaadin uses -->
        <!-- the unbound SLF4J no-operation (NOP) logger implementation -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-testbench</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.github.bonigarcia/webdrivermanager -->
        <dependency>
            <groupId>io.github.bonigarcia</groupId>
            <artifactId>webdrivermanager</artifactId>
            <version>5.3.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <defaultGoal>jetty:run</defaultGoal>
        <plugins>
            <!-- Define newer versions of Java compiler and war plugin to 
                 better support the latest JDK versions. -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.10.1</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.2</version>
            </plugin>
            <!-- Jetty plugin for easy testing without a separate server -->
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>10.0.12</version>
                <configuration>
                    <!--
                    Configures automatic reload of Jetty server
                    (with 2 second timeout) when new classes are compiled 
                    (e.g. by IDEs).
                    Should be disabled when using a proper live reload system,
                    such as JRebel.
                    If using IntelliJ IDEA with autocompilation, this
                    might cause lots of unnecessary compilations in the
                    background. Consider using "0" and trigger restart manually
                    by hitting enter.
                    -->
                    <scan>2</scan>
                    <!-- Use war output directory to get the webpack files -->
                    <!--<webAppConfig>-->
                    <!--    <allowDuplicateFragmentNames>true</allowDuplicateFragmentNames>-->
                    <!--</webAppConfig>-->
                </configuration>
            </plugin>

            <!--
                Take care of synchronizing java dependencies and imports in
                package.json and main.js files.
                It also creates webpack.config.js if not exists yet.
            -->
            <plugin>
                <groupId>com.vaadin</groupId>
                <artifactId>vaadin-maven-plugin</artifactId>
                <version>${vaadin.version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>prepare-frontend</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <!-- Production mode is activated using -Pproduction -->
            <id>production</id>

            <build>
                <plugins>
                    <plugin>
                        <groupId>com.vaadin</groupId>
                        <artifactId>vaadin-maven-plugin</artifactId>
                        <version>${vaadin.version}</version>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>build-frontend</goal>
                                </goals>
                                <phase>compile</phase>
                            </execution>
                        </executions>
                        <configuration>
                            <productionMode>true</productionMode>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>

        <profile>
            <id>it</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.eclipse.jetty</groupId>
                        <artifactId>jetty-maven-plugin</artifactId>
                        <configuration>
                            <!--<scanIntervalSeconds>0</scanIntervalSeconds>-->
                            <stopPort>8081</stopPort>
                            <stopWait>5</stopWait>
                            <stopKey>${project.artifactId}</stopKey>
                        </configuration>
                        <executions>
                            <execution>
                                <id>start-jetty</id>
                                <phase>pre-integration-test</phase>
                                <goals>
                                    <goal>start</goal>
                                </goals>
                            </execution>
                            <execution>
                                <id>stop-jetty</id>
                                <phase>post-integration-test</phase>
                                <goals>
                                    <goal>stop</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>

                    <!-- Runs the integration tests (*IT) after the server is started -->
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-failsafe-plugin</artifactId>
                        <version>3.0.0-M7</version>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>integration-test</goal>
                                    <goal>verify</goal>
                                </goals>
                            </execution>
                        </executions>
                        <configuration>
                            <trimStackTrace>false</trimStackTrace>
                            <enableAssertions>true</enableAssertions>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
</project>

Now I would like to try the pre-release of Vaadin 24.

I understand this new version will have little new in terms of features or fixes. Instead, this new version is aimed at making the transition from being based on Java EE 8 to being based on Jakarta EE 10. As discussed in this Vaadin company blog page, this leap involves (a) the dropping of some deprecated features, and (b) the switching of package names from javax.* to jakarta.*. These changes are part of the transition from Oracle donating Java EE technologies to the Eclipse Foundation to become Jakarta EE.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • By the way, for starting a new project in Vaadin 24 use either Spring-based starter at https://start.vaadin.com/app ***or*** non-Spring alternatives at https://vaadin.com/hello-world-starters – Basil Bourque Mar 11 '23 at 22:18

1 Answers1

7

Official instructions, plus my details

The Vaadin company blog page Vaadin 24 pre-release available for Spring Boot 3.0, provides some instructions for migrating from Vaadin 23 to Vaadin 24. I can supplement that page with more details.

First, migrate to latest Vaadin 23

That page first instructs us to migrate to the latest version of Vaadin 23, currently 23.3.5. We see you did that your existing Maven POM file.

Just be sure to run your app to verify Vaadin 23 is working well before trying Vaadin 24.

Java version

That page says to next ensure that your project can run on Java 17, the latest long-term support version.

We see you did that too in your existing POM, running on Java 19 (the current Java release).

Vaadin version

The official instructions point us to this GitHub page to capture the current latest version of Vaadin 24. There we find 24.0.0.alpha10.

So we paste that version number into the POM.

Servlet spec

Next, look for the javax.servlet-api entry in your POM.

Vaadin 23 and earlier was designed for Java Servlet Specification version 3.1, and is compatible with Java Servlet Spec 4.0.1.

As we jump to Jakarta 10, the name of the spec changes to Jakarta Servlet. And the Servlet Spec is version 6 in Jakarta EE 10. We can verify with a Maven repository such as this one that the latest subversion of Servlet 6 is 6.0.0.

So we change this part of the POM:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>

… to:

<!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
<dependency>
    <groupId>jakarta.servlet</groupId>
    <artifactId>jakarta.servlet-api</artifactId>
    <version>6.0.0</version>
    <scope>provided</scope>
</dependency>

Jetty

Your Vaadin 23 app is bundled with an embedded version of Jetty. This enables you to run your Vaadin web app using Jetty as the deployment web app server within your IDE. This arrangement is convenient, relieving you of the chore of configuring an external web app server.

You may nevertheless choose to use an externally web app server running in its own process, such as Tomcat, a separately-installed Jetty, Glassfish, WildFly, Payara, OpenLiberty, or any of several other such products. But if you wish to use the embedded Jetty within your IDE, read on.

Your existing POM is set to use jetty-maven-plugin version 10.0.x. That corresponds to Jetty 10. That version of Jetty supports Servlet 4.

But we are moving to Servlet 6. That requires a different version of Jetty, Jetty 12. Unfortunately, Jetty 12 seems to be still in development, hosted on GitHub. But 12 is at the alpha stage as of 2023-01. If curious, see this 2022-04 talk on YouTube, Jakarta Tech Talk - Implementing Servlet 6.0 in Jetty.

So we have a predicament, if we want to run Jetty embedded conveniently within our IDE. Technically Vaadin 24 is built for Jakarta 10, which implies Servlet 6. But we only have Jetty 11 available to us, which supports Servlet 5 rather than Servlet 6. But perhaps we might be lucky to find that Vaadin 24, because it has no significant feature changes from Vaadin 23, may not actually be using any new features available only in Servlet 6, nor using any old features deleted from Servlet 6. If so, we may get away with using version of 11.0.13 of jetty-maven-plugin to utilize Jetty 5.

<!-- Jetty plugin for easy testing without a separate server -->
<plugin>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <version>11.0.13</version>
    <configuration>
        <!--
        Configures automatic reload of Jetty server
        (with 2 second timeout) when new classes are compiled 
        (e.g. by IDEs).
        Should be disabeld when using a proper live reload system,
        such as JRebel.
        If using IntelliJ IDEA with autocompilation, this
        might cause lots of unnecessary compilations in the
        background. Consider using "0" and trigger restart manually
        by hitting enter.
        -->
        <scan>2</scan>
        <!-- Use war output directory to get the webpack files -->
        <!--<webAppConfig>-->
        <!--    <allowDuplicateFragmentNames>true</allowDuplicateFragmentNames>-->
        <!--</webAppConfig>-->
    </configuration>
</plugin>

Let’s try it, fingers crossed … yes, success! Using embedded Jetty 11 with Vaadin 24 is working, at least for now.

Voilà

And that is all we need to do to migrate your Vaadin 23 app to Vaadin 24 (alpha 6).

You can use the Maven Jetty plugin command jetty:run to launch your web app just as you do with Vaadin 23.

Here is my resulting Maven POM file.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0"
         xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>project-base</artifactId>
    <name>Project base for Vaadin</name>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>19</maven.compiler.source>
        <maven.compiler.target>19</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <failOnMissingWebXml>false</failOnMissingWebXml>

        <vaadin.version>24.0.0.alpha6</vaadin.version>
        <drivers.downloader.phase>pre-integration-test</drivers.downloader.phase>
    </properties>

    <repositories>
        <!-- The order of definitions matters. Explicitly defining central here to make sure it has the highest priority. -->
        <repository>
            <id>central</id>
            <url>https://repo.maven.apache.org/maven2</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>vaadin-prereleases</id>
            <url>
                https://maven.vaadin.com/vaadin-prereleases/
            </url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <!-- Repository used by many Vaadin add-ons -->
        <repository>
            <id>Vaadin Directory</id>
            <url>https://maven.vaadin.com/vaadin-addons</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

    <pluginRepositories>
        <!-- The order of definitions matters. Explicitly defining central here to make sure it has the highest priority. -->
        <pluginRepository>
            <id>central</id>
            <url>https://repo.maven.apache.org/maven2</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
        <pluginRepository>
            <id>vaadin-prereleases</id>
            <url>
                https://maven.vaadin.com/vaadin-prereleases/
            </url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.vaadin</groupId>
                <artifactId>vaadin-bom</artifactId>
                <type>pom</type>
                <scope>import</scope>
                <version>${vaadin.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>com.vaadin</groupId>
            <!-- Replace artifactId with vaadin-core to use only free components -->
            <artifactId>vaadin</artifactId>
        </dependency>

        <!-- Added to provide logging output as Vaadin uses -->
        <!-- the unbound SLF4J no-operation (NOP) logger implementation -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <version>6.0.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-testbench</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.github.bonigarcia/webdrivermanager -->
        <dependency>
            <groupId>io.github.bonigarcia</groupId>
            <artifactId>webdrivermanager</artifactId>
            <version>5.3.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <defaultGoal>jetty:run</defaultGoal>
        <plugins>
            <!-- Define newer versions of Java compiler and war plugin to 
                 better support the latest JDK versions. -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.10.1</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.2</version>
            </plugin>
            <!-- Jetty plugin for easy testing without a separate server -->
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>11.0.13</version>
                <configuration>
                    <!--
                    Configures automatic reload of Jetty server
                    (with 2 second timeout) when new classes are compiled 
                    (e.g. by IDEs).
                    Should be disabled when using a proper live reload system,
                    such as JRebel.
                    If using IntelliJ IDEA with autocompilation, this
                    might cause lots of unnecessary compilations in the
                    background. Consider using "0" and trigger restart manually
                    by hitting enter.
                    -->
                    <scan>2</scan>
                    <!-- Use war output directory to get the webpack files -->
                    <!--<webAppConfig>-->
                    <!--    <allowDuplicateFragmentNames>true</allowDuplicateFragmentNames>-->
                    <!--</webAppConfig>-->
                </configuration>
            </plugin>

            <!--
                Take care of synchronizing java dependencies and imports in
                package.json and main.js files.
                It also creates webpack.config.js if not exists yet.
            -->
            <plugin>
                <groupId>com.vaadin</groupId>
                <artifactId>vaadin-maven-plugin</artifactId>
                <version>${vaadin.version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>prepare-frontend</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <!-- Production mode is activated using -Pproduction -->
            <id>production</id>

            <build>
                <plugins>
                    <plugin>
                        <groupId>com.vaadin</groupId>
                        <artifactId>vaadin-maven-plugin</artifactId>
                        <version>${vaadin.version}</version>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>build-frontend</goal>
                                </goals>
                                <phase>compile</phase>
                            </execution>
                        </executions>
                        <configuration>
                            <productionMode>true</productionMode>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>

        <profile>
            <id>it</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.eclipse.jetty</groupId>
                        <artifactId>jetty-maven-plugin</artifactId>
                        <configuration>
                            <!--<scanIntervalSeconds>0</scanIntervalSeconds>-->
                            <stopPort>8081</stopPort>
                            <stopWait>5</stopWait>
                            <stopKey>${project.artifactId}</stopKey>
                        </configuration>
                        <executions>
                            <execution>
                                <id>start-jetty</id>
                                <phase>pre-integration-test</phase>
                                <goals>
                                    <goal>start</goal>
                                </goals>
                            </execution>
                            <execution>
                                <id>stop-jetty</id>
                                <phase>post-integration-test</phase>
                                <goals>
                                    <goal>stop</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>

                    <!-- Runs the integration tests (*IT) after the server is started -->
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-failsafe-plugin</artifactId>
                        <version>3.0.0-M7</version>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>integration-test</goal>
                                    <goal>verify</goal>
                                </goals>
                            </execution>
                        </executions>
                        <configuration>
                            <trimStackTrace>false</trimStackTrace>
                            <enableAssertions>true</enableAssertions>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
</project>

External app servers

You may want your IDE to execute with an external app server rather than use the embedded Jetty discussed above.

If so, you’ll need to use a version of your desired server that supports Jakarta EE 10. Here is a partial list.

  • Apache Tomcat 10.1
  • Eclipse Jetty 12
  • Eclipse GlassFish 7
  • Payara 6
  • IBM Open Liberty 22
  • Red Hat WildFly 27
  • … and more
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154