Esportare una webapp in Spring Boot in file .jar

di il
39 risposte

Esportare una webapp in Spring Boot in file .jar

Ho una webapp creata in spring boot 2 che gira su java 11 e vorrei metterla in un container Docker per testarla localmente su localhost in una VM Linux per poi trasferire tutto, in futuro, su una VPS.
Ho scritto un codice Docker ma non funziona e non riesco a capire dove risiede il problema così ho aperto questa discussione per capire se il metodo che uso per creare il file .jar è corretto.
Non uso il .war che sono abituato ad usare e che preferirei perché con Docker non funziona.
Ecco la procedura che ho adottato:
Ho editato la classe con il main in questo modo:
@Profile("docker")
Ho editato application.properties in questo modo:
spring.profiles.active=docker
Ho creato un application-docker.properties con le credenziali di accesso al DB sulla rete privata Docker:
spring.datasource.url=jdbc:postgresql://rete-privata-docker:5432/gis
spring.datasource.username=…
spring.datasource.password=…
Su IntelliJ sono andato in “File/Project Structure”, ho premuto su “Add”, scelto “JAR/From modules with dependencies” e messo la spunta su “Include in project build”.
1) E’ corretto questo oppure devo fare altro?
2) Su Docker non devo aggiungere nessun contenitore Tomcat, giusto? In pratica nel file .jar che si genera c’è già una versione di Tomcat scelta da Spring Boot, giusto? L’unico dubbio è questa dipendenza:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope> 
</dependency>
che riporta lo scope provided. Se edito il file .jar in .zip e lo decomprimo dentro non trovo tomcat-embed-el-9.0-60.jar e questo mi manda in tilt.

39 Risposte

  • Re: Esportare una webapp in Spring Boot in file .jar

    Oh, bentornato. E .... ahhh vedo che ora tiriamo in ballo pure Docker ....
    Allora chiariamo alcune cose.

    iBaffiPro ha scritto:


    Non uso il .war che sono abituato ad usare e che preferirei perché con Docker non funziona.
    Il .war si può anche far funzionare in Docker ma ovviamente nella immagine ci deve anche essere un intero servlet container (es. Tomcat).

    iBaffiPro ha scritto:


    Ecco la procedura che ho adottato:
    Ho editato la classe con il main in questo modo:
    @Profile("docker")
    Ho editato application.properties in questo modo:
    spring.profiles.active=docker
    Non so a che ti serve questo profilo Spring. Di per sé non serve. Se ti serve per "altri" motivi (es. configurazione differente, come è logico), ovviamente ha senso.
    Ma NON serve che ci sia @Profile("docker") sulla classe main. Il profilo lo imposti poi all'avvio della applicazione. Non serve forzare la classe del main per dire "questa classe la attivo solo con il profilo docker"!

    iBaffiPro ha scritto:


    L’unico dubbio è questa dipendenza:
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope> 
    </dependency>
    che riporta lo scope provided.
    Questa dipendenza, così come l'hai scritta con scope provided, serve SOLO quando crei il war. Perché solo in quel caso il Tomcat embedded predefinito va escluso.
    Ma se intendi generare un jar che parte "standalone", il Tomcat embedded serve!! Quindi non lo puoi escludere.
    E ovviamente devi anche avere il <packaging> impostato a jar, non war ovviamente.


    Le questioni però sono anche altre. Come vuoi creare la immagine docker? A più layer? O la tua applicazione con il singolo jar è un layer unico?
    La cosa più semplice è creare un singolo layer per la tua applicazione. Una soluzione un pelino più efficiente (per lo startup più che altro) è pre-spacchettare il jar in modo che nel container sia già espanso.
    Ma se vai a vedere la documentazione ufficiale più guide varie online, ti indicano tutte di fare l'immagine a più layer. Se hai mai notato, il jar finale è bello grosso, parliamo anche di decine di MByte. Ma cosa è che cambia più frequentemente? Cambia di più il TUO codice, che è molto poco rispetto a tutto il resto. Se non cambi versione di Boot, versione di altre dipendenze ecc... hai una base di codice che sostanzialmente non cambia. Questo permette di gestire l'immagine Docker a più layer, con la parte del tuo codice che è solo il layer più estremo mentre il resto può essere riutilizzabile.

    Quindi, in sostanza: la cosa più semplice che puoi iniziare a fare è una immagine con la tua intera applicazione in .jar a singolo layer. Dovrebbero bastare poche righe nel Dockerfile.
  • Re: Esportare una webapp in Spring Boot in file .jar

    Vorrei pubblicare la WebApp in JAVA, con PHP ci riuscivo.
    Se rimuovo l’annotazione @Profile("sviluppo"), il profilo viene caricato correttamente, hai perfettamente ragione. Chissà perché ho deciso di usare questa annotazione in passato. Grazie per aver notato.
    Se posso usare il .war allora bye bye .jar, preferisco di gran lunga usare il .war.
    Vorrei realizzare l’applicazione con un singolo layer, è già fin troppo complicato così. La mia webapp è leggerissima, sono pochi MB e se devo aspettare un secondino in più mentre la carico pazienza. Il mio codice è più leggero di una piuma, questo sì, ma non ha importanza. Non sono così esigente, preferisco finire velocemente e cominciare a leggere il libro sulla nuova versione di java.
    Non è complicato far spacchettare a Docker, se possibile preferisco lavorare sul .war così riesco a pubblicare sullo stesso server anche altre esercitazioni non fatte in Spring Boot. Inoltre, se carico il .war spacchettato non vorrei che Windows mi dicesse che nel progetto ho troppe sottocartelle.
    A mio avviso il problema risiede nella mia app, non nella configurazione di Docker, perché se carico .war non realizzati in Spring Boot, Tomcat li legge tranquillamente e li espone alla porta indicata in docker-compose.
  • Re: Esportare una webapp in Spring Boot in file .jar

    Oggi ho smanettato nuovamente, sicuro delle tue parole e sono riuscito a far funzionare la WebApp. Ci sono ancora alcune cose da sistemare ma almeno l’applicazione ora parte e funziona anche.
    Uno dei problemi che avevo era il nome del file. In pratica se nomino l’applicazione magazzino22.war la WebApp non parte mentre se la nomino ROOT.war parte. Tu probabilmente starai pensando: dov’è il problema? Con Docker si possono rinominare i .war in quello che si vuole prima di spedirli nell’immagine! Verissimo, ma se avessi 3 o 10 war tutti fatti in Spring Boot? Su internet c’è scritto che basta usare JSTL ma se aggiungo questa dipendenza non risolvo.
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
    </dependency>

    Comunque sono off-topic... apro un'altra discussione?
  • Re: Esportare una webapp in Spring Boot in file .jar

    iBaffiPro ha scritto:


    mentre se la nomino ROOT.war parte.
    In Tomcat ROOT.war è semplicemente un nome speciale che identifica la webapp che non ha context-path, ovvero context-root e server-root coincidono. Cioè http://nomehost:porta/ la / è la server-root ma ANCHE la context-root del contesto.
    E ovviamente per ciascuna istanza di Tomcat ce ne può essere solo una di webapp così ....

    Ora, che ti funzioni o no (se non ci sono altri motivi che ignoro), dipende da come hai emesso gli url nelle pagine. Se li hai schiantati presupponendo context-path = / allora OVVIO che funziona solo se fai deploy di ROOT.war .
    Se invece avessi usato i costrutti (es. di Thymeleaf) per emettere gli url gestendo dinamicamente la context-path, allora ti funziona qualunque sia il context-path.

    iBaffiPro ha scritto:


    Su internet c’è scritto che basta usare JSTL ma se aggiungo questa dipendenza non risolvo.
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
    </dependency>
    Ma che c'entra JSTL ?? JSTL è la libreria di custom-tag che si utilizza nelle pagine JSP. Ma tu forse (se ben ricordo) hai usato il template engine Thymeleaf .. quindi ribadisco di nuovo .. che c'entra??
  • Re: Esportare una webapp in Spring Boot in file .jar

    Con Tymeleaf quando inserisco una URL uso questo sistema:
    th:href="@{/bulloni}"
    Nella classe con il main ho questa impostazione:
    System.setProperty("server.servlet.context-path", "/xyz");
    Ma se scrivo:
    https://localhost:7003/xyz
    oppure:
    http://localhost:6003/xyz
    ottengo l'errore 404. Su IntelliJ non ho questo problema.
    Se scrivo:
    https://localhost:7003/
    http://localhost:6003/
    tutto funziona alla perfezione. Al contrario, su IntelliJ, tutto si schianta inesorabilmente come è giusto che sia.
    Se non edito l'app in ROTT.war il sito diventa sempre irraggiungibile, sia con questa impostazione:
    System.setProperty("server.servlet.context-path", "/xyz");
    che con questa:
    //System.setProperty("server.servlet.context-path", "/xyz");
    Ho sbagliato la configurazione di Docker oppure nella WebApp ho dimenticato qualcosa?
    Con PHP facevo in questo modo:
    /index.php > dirotto verso cartella1 (location.href = "cartella1/index.php";)
    /cartella1
    /cartella2
    /cartella3
    Nelle 3 cartelle potevo mettere 3 WebApp differenti come ad esempio WordPress, PrestaShop, ecc... e non era male come soluzione. Con un solo file "index.php" potevo "decidere comodamente i giochi". Questo passaggio con Spring Boot non riesco più a farlo. Se scrivessi un'app in Spring Boot che facesse il lavoro di index.php non riuscirei a caricarla perché dovrebbe chiamarsi ROOT.war per funzionare.
    Se non uso Spring Boot ma delle semplici JSP che implementano JSTL posso caricare su Docker più file .war con nomi difersi. I nomi dei file .war diventano i nomi delle cartelle. Esempio:
    app123.war > /app123.war
    Anche questo approccio comunque non mi fa impazzire perché 123 potrebbe essere un numero che decido di usare per contraddistinguere la versione dell'app e che quindi cambia nel tempo.
    La soluzione migliore sarebbe:
    app-saluto-2.34.war > /saluto
    app-ringraziamento.5.45.war > /grazie
    app-index-4.56.war > / > dirotto la connessione verso /saluto o dove mi va...
    Si riesce a fare questa cosa senza riscrivere tutta la WebApp oppure devo semplicemente perfezionare la configurazione dei miei container Docker?
  • Re: Esportare una webapp in Spring Boot in file .jar

    iBaffiPro ha scritto:


    Con Tymeleaf quando inserisco una URL uso questo sistema:
    th:href="@{/bulloni}"
    Corretto.

    iBaffiPro ha scritto:


    Nella classe con il main ho questa impostazione:
    System.setProperty("server.servlet.context-path", "/xyz");
    Allora, sono quasi certo di avertelo già detto tempo fa: la property server.servlet.context-path funziona e viene considerata SOLO se il server è embedded. Perché è Spring che avvia il core del Tomcat e quindi ne ha pieno controllo e può configurarlo anche sugli aspetti del context-path.

    Ma se fai un war le cose sono parecchio diverse. Perché non c'è solo il core del Tomcat, c'è tutto il resto del Tomcat, anche la parte che va a scansionare la /webapps per trovare file .war o cartelle con l'equivalente già spacchettato.
    E quindi le regole sono quelle di Tomcat. Di norma il context-path dipende dal nome del .war o dal nome della cartella (c'è anche l'opzione più avanzata di agire sulla configurazione di Tomcat nei file .xml).
    Ma il punto è che il TUO codice Java NON ha controllo sul context-path (e tra l'altro con un war l'applicazione NON parte certo dal main(String[] args) ).
  • Re: Esportare una webapp in Spring Boot in file .jar

    Niente da fare non riesco a cavare il ragno dal buco…
    Ho un progetto 1 in Spring Boot su IntelliJ che funziona alla perfezione ed un progetto 2 in Docker che funziona alla perfezione. Il progetto 1 funziona perché in locale viene renderizzato perfettamente nel browser. Il progetto 2 funziona alla perfezione perché se provo ad usarlo con un .jar di un’altra WebApp in Spring Boot non fa una piega.
    Io penso ad un’errata scrittura del file pom.xml, dei file properties oppure ad una errata configurazione dell’IDE (quest’ultima meno probabile).
    Sono giorni che sto smanetto e non so più dove sbattere la testa.
    In pratica sul terminale di Linux (per testare il progetto 2 uso una VM Linux di vmware) ottengo questo errore:
    no main manifest attribute, in /demoapp/Nomefilejar-9.0.jar
    Il file .jar che ottengo è anche troppo piccolo, solo 5MB, ma dovrebbe essere come minimo di 20MB.
    PROGETTO 2
    
    FROM openjdk:11.0.15-jre-slim
    EXPOSE 8080
    EXPOSE 8433
    WORKDIR /demoapp
    COPY jarfile/Nomefilejar-9.0.jar /demoapp/
    CMD ["java", "-jar", "/demoapp/Nomefilejar-9.0.jar"]
    
    PROGETTO 1
    pom.xml
    
    <?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.7.0</version>
            <relativePath/>
        </parent>
        <groupId>it.applicazionijava</groupId>
        <artifactId>gestioneutenti</artifactId>
        <version>9.0</version>
        <packaging>jar</packaging>
        <name>gestioneutenti</name>
        <description>WebApp con Spring Boot, Security, Thymeleaf e PostgreSQL</description>
        <properties>
            <java.version>11</java.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.thymeleaf.extras</groupId>
                <artifactId>thymeleaf-extras-springsecurity5</artifactId>
            </dependency>
            <dependency>
                <groupId>org.postgresql</groupId>
                <artifactId>postgresql</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
                <!--/* <scope>provided</scope> */-->
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jdbc</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-validation</artifactId>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-csv</artifactId>
                <version>1.9.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>5.2.1</version>
            </dependency>
    
        </dependencies>
        <build>
            <finalName>Nomefilejar-${project.version}</finalName>
            <pluginManagement>
                <plugins>
    
                    <plugin>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-maven-plugin</artifactId>
                    </plugin>
    
                    <!--/*
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-compiler-plugin</artifactId>
                    </plugin>
                    */-->
    				
                    <!--/*
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-war-plugin</artifactId>
                        <configuration>
                            <packagingExcludes>
                                WEB-INF/classes/it/applicazionijava/${project.name}/CrittografarePassword.class,
                                WEB-INF/classes/application-sviluppo.properties,
                                WEB-INF/classes/KeyStore.jks,
                                WEB-INF/classes/drop.sql
                            </packagingExcludes>
                        </configuration>
                    </plugin>
                    */-->
    
                </plugins>
            </pluginManagement>
        </build>
    </project>
    
    application-sviluppo.properties
    
    spring.datasource.driver-class-name=org.postgresql.Driver
    spring.datasource.url=jdbc:postgresql://127.0.0.1:5432/...
    spring.datasource.username=...
    spring.datasource.password=...
    spring.sql.init.schema-locations = classpath:drop.sql, classpath:schema.sql
    server.port=8443
    server.address=127.0.0.1
    server.ssl.key-store=classpath:KeyStore.jks
    server.ssl.key-store-password=mysecret
    server.ssl.keyStoreType=JKS
    server.ssl.keyAlias=mydomain
    logging.level.org.springframework=INFO
    spring.sql.init.mode=always
    spring.sql.init.continue-on-error=false
    
    application.properties
    
    spring.datasource.driver-class-name=org.postgresql.Driver
    spring.datasource.url=...
    spring.datasource.username=...
    spring.datasource.password=...
    server.port=8443
    server.ssl.key-store=...
    server.ssl.key-store-password=...
    server.ssl.keyStoreType=...
    server.ssl.keyAlias=...
    logging.level.org.springframework=INFO
    spring.sql.init.mode=always
    spring.sql.init.continue-on-error=false
    
    application-docker.properties
    
    spring.datasource.driver-class-name=org.postgresql.Driver
    spring.datasource.url=jdbc:postgresql://postgresql-postgis:5432/...
    spring.datasource.username=...
    spring.datasource.password=...
    spring.sql.init.schema-locations = classpath:schema.sql
    server.port=8443
    server.address=postgresql-postgis
    server.ssl.key-store=classpath:KeyStore.jks
    server.ssl.key-store-password=mysecret
    server.ssl.keyStoreType=JKS
    server.ssl.keyAlias=mydomain
    logging.level.org.springframework=INFO
    spring.sql.init.mode=always
    spring.sql.init.continue-on-error=false
    
    MANIFEST.MF (aggiunto dall'IDE)
    
    Manifest-Version: 1.0
    Main-Class: it.applicazionijava.gestioneutenti.GestioneUtentiApplication
    
    GestioneUtentiApplication.java
    
    package it.applicazionijava.gestioneutenti;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
    import org.springframework.context.annotation.Profile;
    
    @SpringBootApplication
    
    @Profile("docker")
    public class GestioneUtentiApplication extends SpringBootServletInitializer {
    
    	//@Override
    	//protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    	//	return application.sources(GestioneUtentiApplication.class);
    	//}
    
    	public static void main(String[] args) {
    		System.setProperty("server.servlet.context-path", "/it");
    		SpringApplication.run(GestioneUtentiApplication.class, args);
    	}
    
    }
    
    ConfigurazioneTomcatConHttps.java
    
    package it.applicazionijava.gestioneutenti.autenticazione_spring_security;
    
    import org.apache.catalina.Context;
    import org.apache.catalina.connector.Connector;
    import org.apache.tomcat.util.descriptor.web.SecurityCollection;
    import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
    import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
    import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class ConfigurazioneTomcatConHttps {
        @Bean
        public ServletWebServerFactory servletContainer() {
            TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
                @Override
                protected void postProcessContext(Context context) {
                    SecurityConstraint securityConstraint = new SecurityConstraint();
                    securityConstraint.setUserConstraint("CONFIDENTIAL");
                    SecurityCollection collection = new SecurityCollection();
                    collection.addPattern("/*");
                    securityConstraint.addCollection(collection);
                    context.addConstraint(securityConstraint);
                }
            };
            tomcat.addAdditionalTomcatConnectors(redirectConnector());
            return tomcat;
        }
        private Connector redirectConnector() {
            Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
            connector.setScheme("http");
            connector.setPort(8080);
            connector.setSecure(false);
            connector.setRedirectPort(8443);
            return connector;
        }
    }
    
    Configurazione IntelliJ Idea
    (configurazione per creare il file .jar per Linux)
    (configurazione per creare il file .jar per Linux)


    (configurazione per testare in locale su Windows 10 la webapp)
    (configurazione per testare in locale su Windows 10 la webapp)


    (creazione dell'artifact manuale su IntelliJ)
    (creazione dell'artifact manuale su IntelliJ)

  • Re: Esportare una webapp in Spring Boot in file .jar

    Allora: mi "saltano" all'occhio diverse cose dubbie/sbagliate.

    Innanzitutto nel pom.xml hai usato:

    iBaffiPro ha scritto:


            <pluginManagement>
                <plugins>
    
                    <plugin>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-maven-plugin</artifactId>
                    </plugin>
    Perché <pluginManagement> ? Sai a cosa serve? Non serve per quello che stavi pensando ....

    iBaffiPro ha scritto:


    @Profile("docker")
    public class GestioneUtentiApplication extends SpringBootServletInitializer {
    Come avevo già detto, il @Profile("docker") qui non ha molto senso. @Profile serve per "attivare" un componente Spring solo se è attivo quel tal profilo indicato. Se fai così, puoi avviare l'applicazione solo con il profilo docker e non con altri. Capisci anche tu che non ha molto senso ....

    iBaffiPro ha scritto:


    	public static void main(String[] args) {
    		System.setProperty("server.servlet.context-path", "/it");
    Il server.servlet.context-path, come ti avevo già detto, funziona solo con il server embedded, ok. Ma nota che lo puoi impostare anche nel application properties.

    iBaffiPro ha scritto:


    Sono giorni che sto smanetto e non so più dove sbattere la testa.
    Beh, ci sarà un motivo se io in mezz'ora scrivo e provo il demo Spring Boot per Docker (perfettamente funzionante), che ti ho linkato in privato mentre tu dopo giorni sei ancora lì a sbatterci la testa ....
  • Re: Esportare una webapp in Spring Boot in file .jar

    Grazie mille, il <pluginManagement> mi è sfuggito. Il mio pom precedente era questo:
    		<pluginManagement>
    			<plugins>
    				<plugin>
    					<groupId>org.apache.maven.plugins</groupId>
    					<artifactId>maven-compiler-plugin</artifactId>
    				</plugin>
    				<plugin>
    					<groupId>org.apache.maven.plugins</groupId>
    					<artifactId>maven-war-plugin</artifactId>
    					<configuration>
    						<packagingExcludes>
    							WEB-INF/classes/it/applicazionijava/${project.name}/CrittografarePassword.class,
    							WEB-INF/classes/application-sviluppo.properties,
    							WEB-INF/classes/KeyStore.jks,
    							WEB-INF/classes/funzioni.sql,
    							WEB-INF/classes/drop.sql
    						</packagingExcludes>
    					</configuration>
    				</plugin>
    			</plugins>
    		</pluginManagement>
    @Profile("docker") è stato un errore a postare.
    Il .jar ora è corretto ma c'è ancora qualche errore.
    Ho provato server.address=postgresql-postgis e server.address=localhost ma il più sensato è il secondo perché sono dentro il contenitore.
    KeyStore.jks generato su Windows lo posso usare su qualunque OS?
  • Re: Esportare una webapp in Spring Boot in file .jar

    iBaffiPro ha scritto:


    KeyStore.jks generato su Windows lo posso usare su qualunque OS?
    Sì, non c'entra con un OS specifico.
  • Re: Esportare una webapp in Spring Boot in file .jar

    Server.address è l'IP al quale c'è Tomcat.
    Se Spring Boot e quindi Java prende Tomcat, lo configura ed essendo quest'ultimo contenuto nel file .jar mi viene da pensare che localhost sia la scelta più logica ma non è così. postgresql-postgis è proprio sbagliato perché è la rete del db. Se metto localhost non risolvo. Giusto per verificare se il problema è in quella stringa ho provato brutalmente a mettere 0.0.0.0 e la WebApp magicamente si avvia ma c’è un altro problema il redirect verso la porta 8443 non funziona.
    Se digito:
    https://localhost:6004/it
    dovrei ottenere:
    https://localhost:7004/it
    Invece ottengo:
    https://localhost:8443/it
    Nel docker-compose.yaml c’è scritto questo:
    
        ports:
          - 6004:8080
          - 7004:8443
    
    Tra il resto nel Dockerfile c’è una porta errata ma l'ho corretta.
    
      java:
        build: ./java-sp
        image: imjava
        container_name: conjava
        ports:
          - 6004:8080
          - 7004:8443
        restart: on-failure
        networks:
          - rete
    
    Tra il resto su Docker la pagina di openjdk:11.0.15-jre-slim non è visualizzabile:
    https://hub.docker.com/layers/openjdk/library/openjdk/11.0.15-jre-slim/images/sha256-b278b889aaae027249c1f35f170999dd85e060ca09599c67f4c6f2b27c558448?context=explore
  • Re: Esportare una webapp in Spring Boot in file .jar

    iBaffiPro ha scritto:


    Server.address è l'IP al quale c'è Tomcat.
    Giusto, svista mia ... ho letto troppo velocemente ..

    iBaffiPro ha scritto:


    Se Spring Boot e quindi Java prende Tomcat, lo configura ed essendo quest'ultimo contenuto nel file .jar mi viene da pensare che localhost sia la scelta più logica ma non è così. postgresql-postgis è proprio sbagliato perché è la rete del db. Se metto localhost non risolvo. Giusto per verificare se il problema è in quella stringa ho provato brutalmente a mettere 0.0.0.0 e la WebApp magicamente si avvia
    0.0.0.0 per un server significa mettersi "in ascolto" su qualunque interfaccia di rete presente .. e non solo sul localhost (ovvero proprio la macchina sé stessa dall'interno). È un concetto generale del networking .. non di Java/Spring.

    Tra l'altro, 0.0.0.0 è il default in Spring Boot. Sei tu che mettendo server.address=localhost hai "ristretto" al solo localhost di fatto "chiudendo" la webapp nel container.

    iBaffiPro ha scritto:


    ma c’è un altro problema il redirect verso la porta 8443 non funziona.

    Nel docker-compose.yaml c’è scritto questo:
    
        ports:
          - 6004:8080
          - 7004:8443
    
    La questione è questa:
    +-------------------------------------
    | Macchina fisica (Host)
    |              +----------------------
    |              | Docker
    |              |    +-----------------
    |              |    | container webapp
    |  6004 *------|----|--* 8080
    |              |    |
    |  7004 *------|----|--* 8443
    |              |    |
    |              |    +-----------------
    |              |
    .              +----------------------
    .
    Dal Host (tua macchina fisica) con il browser andrai su http://localhost:6004 ma se hai impostato un redirect per SSL, la webapp risponde al client con un redirect, il classico status 301 Moved Permanently, indicando anche la Location (url) a cui andare. Già ma a quale url? E soprattutto a QUALE porta?

    NON può indicare 8443 (quello che tu hai messo nel connector.setRedirectPort(8443); ) perché questa è la porta che è solo nota al container e NON alla tua macchina Host che non ne "sa" nulla! (è Docker che fa "vedere" al Host la 7004 girando tutto sulla 8443 del container).

    Quindi a ragion logica, dovrebbe fare un redirect sulla porta 7004. Riguardo il hostname invece dovrei ragionarci un attimo.
    Non so dire in questo momento se (e quale) soluzione c'è che sia "pulita" e generale in questi scenari con Docker, non ne sono ancora ferratissimo. Non sono nemmeno un sistemista (né DevOps) ....

    Queste cose sono un po' "articolate" per me ... figuriamoci per te. Secondo me sei già andato molto OLTRE al punto in cui potevi/dovevi fermarti.
    Tra un mese di cosa parleremo?? Di Kubernetes? (di cui purtroppo non so proprio nulla, mai usato finora) E tra due mesi? Di Serverless sul Cloud?
  • Re: Esportare una webapp in Spring Boot in file .jar

    Per quanto riguarda la porta posso risolvere brutalmente esponendo solo la porta 8080 se non ti vengono in mente idee migliori.
    Il redirect sulla porta 7004 non la voglio fare perché è una soluzione molto sporca. Comunque questo 7004 diventerà 80 sul server.
    Voglio pubblicare l'app. Se non si riesce a pubblicare un'app molto semplice come posso pensare di pubblicare app più complesse. Inoltre la configurazione di Docker è essenziale perché rende chiari alcuni concetti e chiarisce la configurazione ottimale del pom.xml. Non posso assolutamente trascurare questa parte.
    Non conosco Kubernetes e spero vivamente di non dover usare questo strumento.
    Comunque con questo 0.0.0.0 ottengo questo errore:
    container-java-eb     | 2022-05-29 21:54:37.464 DEBUG 1 --- [0.0-8443-exec-8] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, application/xhtml+xml, image/avif, image/webp, application/xml;q=0.9, */*;q=0.8]
    container-java-eb     | 2022-05-29 21:54:37.468 ERROR 1 --- [0.0-8443-exec-8] org.thymeleaf.TemplateEngine             : [THYMELEAF][https-jsse-nio-0.0.0.0-8443-exec-8] Exception processing template "/test-server-asincrono": Error resolving template [/test-server-asincrono], template might not exist or might not be accessible by any of the configured Template Resolvers
    container-java-eb     |
    Ho trovato questa discussione:
    https://stackoverflow.com/questions/72406562/error-resolving-template-template-might-not-exist-or-might-not-be-accessible-by
    ma il mio pom.xml sembra ok:
    
    <?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
    
            <version>2.7.0</version>
            <relativePath/>
        </parent>
    
        <groupId>it.applicazionijava</groupId>
    
        <artifactId>gestioneutenti</artifactId>
    
        <version>10.0</version>
    
        <packaging>jar</packaging>
    
        <name>gestioneutenti</name>
    
        <description>WebApp con Spring Boot, Security, Thymeleaf e PostgreSQL</description>
    
        <properties>
    
            <java.version>11</java.version>
    
        </properties>
        <dependencies>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.thymeleaf.extras</groupId>
                <artifactId>thymeleaf-extras-springsecurity5</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.postgresql</groupId>
                <artifactId>postgresql</artifactId>
                <scope>runtime</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-test</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <optional>true</optional>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jdbc</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-validation</artifactId>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-csv</artifactId>
                <version>1.9.0</version>
            </dependency>
    
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>5.2.1</version>
            </dependency>
    
        </dependencies>
        <build>
            <finalName>prova-${project.version}</finalName>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    
    application-docker.properties
    
    spring.datasource.driver-class-name=org.postgresql.Driver
    spring.datasource.url=jdbc:postgresql://postgresql-postgis:5432/...
    spring.datasource.username=eb
    spring.datasource.password=password
    spring.sql.init.schema-locations = classpath:schema.sql
    server.port=8443
    server.address=0.0.0.0
    server.ssl.key-store=classpath:KeyStore.jks
    server.ssl.key-store-password=mysecret
    server.ssl.keyStoreType=JKS
    server.ssl.keyAlias=mydomain
    logging.level.org.springframework=DEBUG
    spring.sql.init.mode=always
    spring.sql.init.continue-on-error=false
    
  • Re: Esportare una webapp in Spring Boot in file .jar

    iBaffiPro ha scritto:


    Voglio pubblicare l'app. Se non si riesce a pubblicare un'app molto semplice come posso pensare di pubblicare app più complesse. Inoltre la configurazione di Docker è essenziale perché rende chiari alcuni concetti e chiarisce la configurazione ottimale del pom.xml.
    Ho capito che vuoi "pubblicare" online il progetto ..... ma dove sta scritto (o chi ti ha detto) che devi per forza usare Docker?? Cioè .. ovviamente dipende dal servizio/infrastruttura che scegli ma ti posso assicurare che la maggior parte degli hosting Java veri, "commerciali", che trovi su internet (quelli che offrono un Tomcat o altro Servlet container), NON ti mette certo a disposizione un Docker!
    E quindi, un Docker lo trovi dove?? Ma soprattutto (curiosità mia) a quale prezzo?
    Se scegli le strade più tortuose per fare le cose .... io non so proprio che dirti ....

    iBaffiPro ha scritto:


    Comunque con questo 0.0.0.0 ottengo questo errore:
    container-java-eb     | 2022-05-29 21:54:37.464 DEBUG 1 --- [0.0-8443-exec-8] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, application/xhtml+xml, image/avif, image/webp, application/xml;q=0.9, */*;q=0.8]
    container-java-eb     | 2022-05-29 21:54:37.468 ERROR 1 --- [0.0-8443-exec-8] org.thymeleaf.TemplateEngine             : [THYMELEAF][https-jsse-nio-0.0.0.0-8443-exec-8] Exception processing template "/test-server-asincrono": Error resolving template [/test-server-asincrono], template might not exist or might not be accessible by any of the configured Template Resolvers
    container-java-eb     |
    A me NON sembra affatto una cosa relativa al server address 0.0.0.0 (che comunque, come ti avevo già detto, è il default in Spring Boot). Il messaggio è chiaro "non trova il template". Verifica.

    (quel https-jsse-nio-0.0.0.0-8443-exec-8 è solo il nome del thread, non è rilevante)
Devi accedere o registrarti per scrivere nel forum
39 risposte