Updated: Apr 16, 2022
there are a lot of ways building a nice web application with a frontend, backend and a database. the technology stack can have a huge variety nowadays. one can pick almost any modern language for one of the three layers (presentation layer (frontend), logic layer (backend), data layer (database)) or using only one programming language for all of them.
being a java full stack developer means, that one can build the entire application using only one programming language (except version control, package manager and ci/cd). over the the past two decades, java has undergone many transformations.
if one had to jump back in time to the year 1997, the options would be very limited, but it was still possible to be a full stack java developer. sockets could be used as a server or http listener, the jdbc (java database connectivity) driver could be used to connect to the database and the graphical web interface could be made using plain html. this stack is marked in red in figure 1. 
with the release of j2ee 1.4 and later the release of java ee 5, the more advanced java servlets and jsp (java server pages) as well as jpa (java persistence api) were introduced. thanks to these new libraries a way more powerful web app could be build using xml and el (expression language). the new java persistence api provided a new and easy way to map pojos (plain old java objects) to the database using an or (object relational) mapper. if the application uses servlets or jsp a servlet or jsp container is required. a lightweight option was jetty. this stack is marked in orange in figure 1. 
although jsf (java or nowadays called jakarta server faces) was released already in java ee 5, but was really valuable since jakarta ee and the application server wildfly. jsf is more advanced than jsp but still somehow similar and jsf can be programmed using xml or java. this stack is marked in yellow in figure 1. 
an alternative way can be vaadin in combination with a spring boot backend, spring data with a no sql database like mongo db as the persistence layer and an embedded tomcat as the application server. this is personally my most favorite java stack to use. in spring boot it has always been convention over configuration, so if one keeps things at default, no configuration is needed at all. this keeps development fast. creating a new project is fast, too. spring boot cli or the spring initializer let one create a project in about a minute. 
of course this is only my personal favorite. nowadays the opportunities of technologies is very high, specially if one works with jakarta ee or spring boot. so picking the right libs can depend on requirements or personal taste. so knowing what options java offers might help picking the most fitting tools for the project if one wants to build an application fully covered by java technologies.