I cannot spot any problem with your code. But I can provide an entire working example app for you to compare
My example app goes along the lines laid out in your Question's code. A Vaadin Button
performs a database query using a DataSource
object from a table of user names. The value from the first row found is displayed in a Vaadin Label
widget on the web page.

This app was built and run with Vaadin 14.1.5 using a "Plain Java Servlet" flavor of a starter project provided by the Vaadin.com site. Running on macOS Mojave with the bundled Jetty web container.
My only changes to their Maven POM file was to change to Java version 13, and to add a dependency for H2 Database Engine to make this a self-contained example using an in-memory database.
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</dependency>
I used the hook for Vaadin starting, to establish my DataSource
object and initialize the database. Following the manual, nested in the resources
folder, I created folders META-INF
> services
. Per the Java SPI facility, there I created a file named com.vaadin.flow.server.VaadinServiceInitListener
containing a single line to specify the name of my class that implements the interface named in the name of this file:
work.basil.example.ApplicationServiceInitListener
That is, my ApplicationServiceInitListener
class implement the Vaadin interface VaadinServiceInitListener
. My class will be automatically instantiated and its method invoked via that Java SPI facility when my Vaadin web app launches.
My ApplicationServiceInitListener
class:
package work.basil.example;
import com.vaadin.flow.server.ServiceInitEvent;
import com.vaadin.flow.server.VaadinServiceInitListener;
import org.h2.jdbcx.JdbcDataSource;
public class ApplicationServiceInitListener implements VaadinServiceInitListener
{
@Override
public void serviceInit ( ServiceInitEvent serviceInitEvent )
{
System.out.println( "DEBUG Running `serviceInit` of " + this.getClass().getCanonicalName() );
// Database work.
prepareDataSource();
App.INSTANCE.provideDatabase().initializeDatabase();
}
private void prepareDataSource ( )
{
JdbcDataSource ds = new JdbcDataSource();
ds.setURL( "jdbc:h2:mem:demo;DB_CLOSE_DELAY=-1" );
ds.setUser( "scott" );
ds.setPassword( "tiger" );
App.INSTANCE.rememberDataSource( ds );
}
}
That class calls my App
class which acts as a sort of service locator. Designed as a singleton via enum.
package work.basil.example;
import javax.sql.DataSource;
import java.util.Objects;
public enum App
{
INSTANCE;
// -------| DataSource |---------------------------------
private DataSource dataSource;
public DataSource provideDataSource ( )
{
return this.dataSource;
}
public void rememberDataSource ( DataSource dataSource )
{
this.dataSource = Objects.requireNonNull( dataSource );
}
// -------| Database |---------------------------------
private Database database;
public Database provideDatabase ( )
{
return new Database();
}
}
That class calls my Database
class. In real work, Database
would be an interface with various concrete implementations for testing versus deployment. I ignored that here for demonstration purposes.
package work.basil.example;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Database
{
public String getFirstUserName ( )
{
String userName = "QUERY-FAILED";
String newline = "\n";
StringBuilder sql = new StringBuilder();
sql.append( "SELECT name_ from user_ ; " ).append( newline );
System.out.println( "sql = " + sql );
try (
Connection conn = App.INSTANCE.provideDataSource().getConnection() ;
Statement statement = conn.createStatement() ;
ResultSet resultSet = statement.executeQuery( sql.toString() ) ;
)
{
while ( resultSet.next() )
{
userName = resultSet.getString( "name_" );
break; // Go no further. We need only the first row found.
}
}
catch ( SQLException e )
{
e.printStackTrace();
}
return userName;
}
public void initializeDatabase ( )
{
System.out.println( "DEBUG Running `initializeDatabase` of " + this.getClass().getCanonicalName() );
String newline = "\n";
// Create table.
StringBuilder sql = new StringBuilder();
sql.append( "CREATE TABLE user_ ( " ).append( newline );
sql.append( "pkey_ IDENTITY NOT NULL PRIMARY KEY , " ).append( newline ); // `identity` = auto-incrementing long integer.
sql.append( "name_ VARCHAR NOT NULL " ).append( newline );
sql.append( ") " ).append( newline );
sql.append( ";" ).append( newline );
System.out.println( "sql = " + sql );
try (
Connection conn = App.INSTANCE.provideDataSource().getConnection() ;
Statement statement = conn.createStatement() ;
)
{
statement.executeUpdate( sql.toString() );
}
catch ( SQLException e )
{
e.printStackTrace();
}
System.out.println("DEBUG Finished `CREATE TABLE` statement.");
// Populate table.
sql = new StringBuilder();
sql.append( "INSERT INTO user_ ( name_ ) " ).append( newline );
sql.append( "VALUES " ).append( newline );
sql.append( "( 'Alice' ) , " ).append( newline );
sql.append( "( 'Bob' ) , " ).append( newline );
sql.append( "( 'Carol' ) " ).append( newline );
sql.append( ";" ).append( newline );
System.out.println( "sql = " + sql );
try (
Connection conn = App.INSTANCE.provideDataSource().getConnection() ;
Statement statement = conn.createStatement() ;
)
{
int rowsAffected = statement.executeUpdate( sql.toString() );
System.out.println( "DEBUG Inserted rows into name_ table: " + rowsAffected );
}
catch ( SQLException e )
{
e.printStackTrace();
}
System.out.println("DEBUG Finished `INSERT` statement.");
}
}
And lastly, the MainView
class. I disable the @PWA
annotation as we are not using that feature for progressive web apps.
package work.basil.example;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;
/**
* The main view contains a button and a click listener.
*/
@Route ( "" )
//@PWA ( name = "Project Base for Vaadin", shortName = "Project Base" )
public class MainView extends VerticalLayout
{
private Label label;
private Button button;
public MainView ( )
{
// Widgets
this.label = new Label( "User: ?" );
this.button = new Button(
"Get user" ,
event -> {
Notification.show( "Getting user." );
String userName = App.INSTANCE.provideDatabase().getFirstUserName();
this.label.setText( "User: " + userName );
}
);
add( button );
// Arrange
this.add( label , button );
}
}