Verificare se la mia webapp in Spring Boot funziona in una cartella qualsiasi del context-path

di il
8 risposte

Verificare se la mia webapp in Spring Boot funziona in una cartella qualsiasi del context-path

Vorrei creare un file .war che funzioni anche in una cartella diversa dal context-path. Per fare questa verifica ho editato il main() in questo modo:

package it.webapp.script;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Profile;
@SpringBootApplication
@Profile("sviluppo")
public class ScriptApplication {
	public static void main(String[] args) {
		System.setProperty("server.servlet.context-path", "/webapp");
		SpringApplication.run(ScriptApplication.class, args);
	}
}
e ho scoperto che il file error.html gestito da Thymeleaf non entra in funzione quando digito http://localhost:8080 a cui ovviamente non corrisponde nessuna risorsa.
Come risolvo?

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Errore</title>
</head>
<body>
<th:block th:include="/_menu"></th:block>
<h3 style="color: #366bbc;">Si &egrave; verificato un errore!</h3>
<div>La pagina che stai cercando non esiste oppure &egrave; stata rimossa.</div>
</body>
</html>
Resto comunque scettico sull'uso di System.setProperty e preferirei testare fisicamente la WebApp lanciando essa in un context-path diverso dalla radice "/".
Per fare questo provo a creare un server Tomcat su IntelliJ. Precisamente nella scheda Server metto "http://localhost:8080/webapp" e nella scheda Deployment, in application context scrivo "/webapp".
Ottengo questo errore inspegabile:

NOTE: Picked up JDK_JAVA_OPTIONS:  --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED
Come rendo la pagina error.html di Thymeleaf e come devo configurare IntelliJ per avere l'effetto di System.setProperty?

8 Risposte

  • Re: Verificare se la mia webapp in Spring Boot funziona in una cartella qualsiasi del context-path

    iBaffiPro ha scritto:


    Vorrei creare un file .war che funzioni anche in una cartella diversa dal context-path. Per fare questa verifica ho editato il main() in questo modo:
    
    		System.setProperty("server.servlet.context-path", "/webapp");
    
    No, chiariamo una cosa innanzitutto. Se il progetto genera un file .war, questo dovrà poi essere deployato (a mano o in maniera (semi-)automatica) su un servlet-container altrove a scelta (es. Tomcat). In un contesto di questo tipo, NON è l'applicazione che può decidere il nome del context-path. Se il build ha generato un myapp.war ma tu lo rinomini in pippo.war e fai il deploy, il context-path sarà ... /pippo.
    In generale, se fai il deploy di un war, il context-path è il nome del war (estensione esclusa). A meno di andare a fare altre impostazioni specifiche del server.

    Quindi non c'è alcuna system-property che puoi impostare per cambiare il context-path. Nemmeno server.servlet.context-path. Discorso diverso, invece, se il server è "embedded", perché l'applicazione ha il controllo del server e di come fare ad agganciarci la webapp. In questo caso, si può usare server.servlet.context-path .

    Se la questione è: come fare in modo che l'applicazione "funzioni" indipendentemente dal context-path, la questione è semplice. Nelle pagine della webapp semplicemente non devi "cablare" (schiantare fisso nel codice) il context-path ma usare dei meccanismi che permettono di emettere in output automaticamente il context-path.

    E in Thymeleaf il modo c'è, il famoso url expression @{ .... }

    Se hai un metodo di controller che risponde a /prodotti.html (dove / è la root del contesto), allora in una pagina

    <a th:href="@{/prodotti.html}">Mostra i prodotti</a>

    emetterà sempre l'url con il giusto context-path (es. /myapp/prodotti.html o /pippo/prodotti.html ecc...).


    P.S. se fai un war l'applicazione non parte col main()
  • Re: Verificare se la mia webapp in Spring Boot funziona in una cartella qualsiasi del context-path

    Io uso la @ e l'applicazione funziona alla perfezione. Non uso la @ con include perché l'IDE mi dice che è sbagliato.
    Comunque il menu viene caricato correttamente in tutte le pagine e non da problemi.
    Per sicurezza ho rimosso il menu nella pagina di error.html ma ottengo lo stesso problema.
    Se digito http://localhost:8080/webapp/dfbhdfshnd la pagina error.html viene raggiunta ma se digito http://localhost:8080 error.html non viene raggiunta.
    Qualche secondo fa ho provato ad aggiungere una classe per gestire gli errori ma non risolvo:
    package it.webapp.script.pagine_web_spring_boot;
    
    import org.springframework.boot.web.servlet.error.ErrorController;
    import org.springframework.http.HttpStatus;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.http.HttpServletRequest;
    
    public class ControlloPagineErrore implements ErrorController {
    
        @RequestMapping("/error")
        public String handleError(HttpServletRequest request) {
            Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
    
            if (status != null) {
                Integer statusCode = Integer.valueOf(status.toString());
    
                if(statusCode == HttpStatus.NOT_FOUND.value()) {
                    return "error"; // error-404.html (da preparare)
                }
                else if(statusCode == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
                    return "error"; // vedi sopra...
                }
            }
            return "error";
        }
    
        @Override
        public String getErrorPath() {
            return null;
        }
    }
    Sembra che Thymeleaf funzioni solo su /webapp e non su /. Non c'è modo per catturare sempre l'errore 404 e non solo su una precisa URL?
  • Re: Verificare se la mia webapp in Spring Boot funziona in una cartella qualsiasi del context-path

    iBaffiPro ha scritto:


    Io uso la @ e l'applicazione funziona alla perfezione.
    Quindi usi già gli url expression di Thymeleaf, quelli "context-relative" cioè @{/blabla} ? Allora ok, è il giusto/minimo da fare.

    L'alternativa altrimenti sarebbe: a) schiantare il context-path nel codice (pessima idea) oppure b) cercare di usare il più possibile url "relativi" es. <a href="../altro"> oppure <img src="subdir/bla.gif"> che va bene solo se l'applicazione è relativamente piccola e con url semplici. Altrimenti per applicazioni grosse ti sfugge di mano la cosa molto velocemente ....

    iBaffiPro ha scritto:


    Non uso la @ con include perché l'IDE mi dice che è sbagliato.
    Non ho capito di cosa parli ..

    iBaffiPro ha scritto:


    Se digito http://localhost:8080/webapp/dfbhdfshnd la pagina error.html viene raggiunta ma se digito http://localhost:8080 error.html non viene raggiunta.
    NOooooo. I servlet-container tengono assolutamente ben separati i contesti delle applicazioni e "girano" alla applicazione SOLO le richieste per gli url che vanno davvero "sotto" quel contesto.

    Se hai una webapp sotto nomecontesto1:

    http://host:porta/nomecontesto1/blabla

    e poi vengono invocati gli url:

    http://host:porta/nomecontesto2/cavolaccio-di-url
    http://host:porta/cavolaccio-di-url

    NESSUNA di queste due richieste può finire alla applicazione deployata sotto il /nomecontesto1. È il servlet-container che garantisce questo, sarebbe un grave problema di sicurezza/privacy se potesse farlo. E non puoi fare nulla lato applicazione per poter ricevere quelle richieste.

    E te lo dico subito: funziona così, punto.

    Chiarisciti questi concetti fondamentali sui servlet-container. Non puoi fare applicazioni Spring-Boot e avere queste lacune grosse come la Torre Eiffel ....


    P.S. se ti dà fastidio allora avere una context-path, puoi fare il deploy della applicazione "alla radice", ovvero quando la context-root e la server-root sostanzialmente coincidono. Con Tomcat basta fare un file che si chiama ROOT.war (ROOT maiuscolo). Chiaramente si può avere solo una webapp così nella istanza del server e presuppone, chiaramente, di avere pieno controllo del server.
    Se ci sono anche altre webapp su contesti specifici oltre alla webapp "root", se non sbaglio prevale il contesto specifico se l'url cade in quel contesto.
  • Re: Verificare se la mia webapp in Spring Boot funziona in una cartella qualsiasi del context-path

    Ho capito, grazie.
    Sul server dovrò usare un file .htaccess con questo codice?
    ErrorDocument 404 http://www.nomesito.it/webapp/script-3.0/error.html
    Nella cartella apposita che dovrà predispormi il sistemista a cui potrò accedere con FileZilla dovrò mettere:
    .../webapp/script-3.0.war
    .../.htaccess

    oppure:
    .../script-3.0.war
    .../.htaccess

    ?
    Il tag al quale mi riferivo sopra è questo:
    <th:block th:include="/_menu"></th:block>
    Come vedi non c'è la @ perché IntelliJ mi dice di non metterla.
    E' corretto scrivere il tag in questo modo?
  • Re: Verificare se la mia webapp in Spring Boot funziona in una cartella qualsiasi del context-path

    iBaffiPro ha scritto:


    Sul server dovrò usare un file .htaccess con questo codice?
    ErrorDocument 404 http://www.nomesito.it/webapp/script-3.0/error.html
    Chiariamo una cosa: i file .htaccess non li gestisce Apache Tomcat, si usano con il Apache HTTPd che è il server HTTP "puro".
    Quindi come è fatta la infrastruttura? C'è solo il Apache Tomcat o c'è Apache HTTPd + Apache Tomcat?
    Ci possono essere vari ottimi motivi per mettere "davanti" il Apache HTTPd, ad esempio per fare logiche di url rewriting o perché il servizio gestisce anche siti in PHP per cui si mette il modulo mod_php in Apache HTTPd per "girare" certe richieste all'interprete PHP.

    Non lo posso sapere io, lo devi sapere tu ...

    E poi: error.html è un file "statico"? (se sì, ovviamente non puoi usare nulla di Thymeleaf) O è gestito da un controller?

    iBaffiPro ha scritto:


    Nella cartella apposita che dovrà predispormi il sistemista a cui potrò accedere con FileZilla dovrò mettere:
    .../webapp/script-3.0.war
    .../.htaccess

    oppure:
    .../script-3.0.war
    .../.htaccess

    ?
    Innanzitutto, di norma, il nome del WAR è il nome del contesto. Quindi attenzione a non metterci numeri di versione.

    Poi comunque il Tomcat è "tuo"? Cioè è a tua completa disposizione? Se sì allora è ragionevole pensare che hai accesso diretto alla cartella webapps/ di Tomcat dove puoi depositare i war. E probabilmente hai accesso anche più "sopra", alla home del Tomcat, alla sua conf/, work/ ecc....

    Se invece il Tomcat non è "solo per te" ma è usato anche da altri, allora DUBITO altamente che hai accesso alla webapps/ e al resto di Tomcat. In uno scenario del genere il deploy lo si fa tipicamente da un pannello di controllo dove si fa un "upload" del war in maniera molto "controllata".

    Anche questo: non lo posso sapere io, lo devi sapere tu ...

    E riguardo come vengono gestiti gli url verso la webapp, dipende ....

    Non è stata fatta alcuna logica particolare per cui dall'esterno si DEVE chiedere:
    http://tuodominio/nomecontesto/home.html
    ?

    Oppure è stata fatta una logica di url rewriting (con il HTTPd) per cui se dall'esterno si chiede:
    http://tuodominio/home.html
    questo viene "riscritto" e girato internamente al Tomcat come /nomecontesto/home.html
    ?

    Se fosse quest'ultimo caso, NON ti devi nemmeno preoccupare delle pagine di errore per altri url, perché non sarebbe possibile andare più "sopra" o in un altro contesto. In quanto tutto è già girato verso il TUO contesto.

    Anche questo: non lo posso sapere io, lo devi sapere tu ...

    iBaffiPro ha scritto:


    Il tag al quale mi riferivo sopra è questo:
    <th:block th:include="/_menu"></th:block>
    Come vedi non c'è la @ perché IntelliJ mi dice di non metterla.
    E' corretto scrivere il tag in questo modo?
    Il th:include "non è più raccomandato" a partire da Thymeleaf 3.0. È scritto nella documentazione di Thymeleaf!
  • Re: Verificare se la mia webapp in Spring Boot funziona in una cartella qualsiasi del context-path

    Grazie per le delucidazioni, direi che al momento è prematuro parlarne.
    Al posto di include che mi piace tanto cosa dovrei usare?
    Avevo visto un'esercitazione in cui si usava una sola pagina come modello e poi nei singoli file si metteva il body, è così che dovrei fare?
  • Re: Verificare se la mia webapp in Spring Boot funziona in una cartella qualsiasi del context-path

    iBaffiPro ha scritto:


    Al posto di include che mi piace tanto cosa dovrei usare?
    Avevo visto un'esercitazione in cui si usava una sola pagina come modello e poi nei singoli file si metteva il body, è così che dovrei fare?
    In realtà ci sono anche th:insert e th:replace.
    La differenza tra i 3 è ben spiegata (con esempio) nella documentazione:
  • Re: Verificare se la mia webapp in Spring Boot funziona in una cartella qualsiasi del context-path

    Grazie mille
Devi accedere o registrarti per scrivere nel forum
8 risposte