Using Vaadin and getting database are orthogonal issues, not really related to one another.
DataSource
interface
Usually best to define a DataSource
object for your particular database.
Take for example the H2 Database Engine and its DataSource
implementation.
// Setup the data source.
JdbcDataSource ds = new JdbcDataSource();
ds.setURL("jdbc:h2:˜/test");
ds.setUser("sa");
ds.setPassword("sa");
return ds ; // Return as a `DataSource` object rather than concrete class.
Study your particular JDBC driver to find its likely implementation(s) of DataSource
. For example, the JDBC driver for Postgres by postgresql.org provides org.postgresql.ds.PGConnectionPoolDataSource
(pooled) and org.postgresql.ds.PGSimpleDataSource
(non-pooled).
Then ask that object for a database connection when you need to talk with the database. When done with that database operation, close the connection.
Connection conn = myDataSource.getConnection() ;
You can use Java try-with-resources syntax to do so simply.
try (
Connection conn = myDataSource.getConnection() ;
)
{
…
// Use `conn` object to work with database.
// When going out of scope here, the connection's `close` method is automatically called.
}
Some people highly recommend using connection pooling. I do not recommend connection pooling, except to remedy a proven problem. Connection pooling is surprisingly tricky to get right, with several notoriously failed projects, and still other projects that do not even recommend themselves for production use. And even if implemented well, connection pooling always brings additional issues such as connections returned to the pool in bad condition such as a transaction left hanging open. Starting with a fresh connection each time is the safest route. Some people decry the expense of obtaining fresh database connections. But I have not seen evidence of that expense in either my own experience or presented by others objectively with formal testing.
If you nevertheless decide to use pooling, your DataSource
implementation can handle the pool behind the scenes. So the code and concepts discussed in this Answer hold for both pooled and non-pooled data source objects. That is the point of the DataSource
interface, to mask over differences such as pooled versus non-pooled. See Oracle Tutorial.
ServletContext
and “attributes”</h1>
The issue then becomes where to store your DataSource
object. Here is where Vaadin comes into the picture.
Vaadin is based on Jakarta Servlet (formerly known as Java Servlet) technology. Actually, Vaadin is one big servlet. Your Vaadin web runs on a server capable of hosting servlets. That server is required to support the Jakarta Servlet specification. That spec requires support for a javax.servlet.ServletContext
object that represents your entire running web app. One "context" has zero, one, or more "session" objects currently running your web app, one session per user per web browser.
Where it gets interesting for our purpose is that ServletContext
provides a cache for any objects you might want to keep around to be available to all the sessions (users) of your app. This cache is known as "attributes", a key-value collection where the key is a String
. You could store your DataSource
here with something like "javax.sql.DataSource"
as the key.
So how to get access to the ServletContext
object representing our web app? See this Question for explanation and possibly better approaches.
ServletContext servletContext =
VaadinServletService // com.vaadin.flow.server.VaadinServletService
.getCurrentServletRequest() // Returns a javax.servlet.http.HttpServletRequest
.getServletContext() // Returns a `javax.servlet.ServletContext`.
;
Now we can store our DataSource
implementation object. We can use any String
as long as it is distinct within the key-value collection. Tip: Prefix your key strings with your own domain name to ensure uniqueness.
servletContext.setAttribute( "com.example-javax.sql.DataSource" , dataSource ) ;
And retrieval by any code needing access to the database. The key-value collection stores the value as an Object
, so we must cast.
DataSource dataSource = (DataSource) servletContext.getAttribute( "com.example-javax.sql.DataSource" ) ;
Tip: You should probably test for NULL result.
Your points
What I don't want is to instatiate connection at each session.
No, you do not want to create a database connection per session, not normally. Maintaining an open database connection ties up resources on both the client and the server (memory, CPU, ports, etc.).
When you need to do database work, ask your DataSource
object for a Connection
. When done with the database, call Connection::close
or let try-with-resources syntax do so automatically.
In my understading though, vaadin works at session level.
Vaadin is just a Jakarta Servlet. And servlets are just web apps that delegate most of the HTTP and web work to a web container such as Tomcat or Jetty or Glassfish etc.
Part of common web work is to create the illusion of a stateful connection despite HTTP’s stateless request-response architecture. Cookies or other tricks are used to track a single user between multiple requests. A Servlet-based web container handles this on our behalf as web app programmers, creating objects to track each user as a "session". And there is nothing special about Vaadin in this regard.
Is it possible to create a class which will persist no matter sessions, and then, vaadin session will query it to get the database connection?
Vaadin and database connections are two topics not directly related to one another.
I suggest you do some more study to get really clear on basic Web technology to understand how HTTP requests/responses work, and how sessions create the illusion of stateful connections. This applies to all web work, not just Vaadin. Vaadin builds upon this foundation, so to understand Vaadin you need to understand the basics of the Web.