Problémy při vytváření webového projektu v Javě

Pokud si necháme vygenerovat projekt pomocí mavenu: File -> New -> Maven project -> maven-archetype-webapp (verze 1.0) -> … a pokud tento projekt nasadíme na Tomcat, zobrazí se očekávaný výstup – jednoduchá stránka s textem „Hello World!“. Problém nastane v okamžiku, kdy začneme používat jsp.
Když původní jednoduchou stránku

<html>
<body>
<h2>Hello World!</h2>
</body>
</html>

nahradíme například tímto:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ prefix="c" taglib uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login</title>
</head>
<body>
	<c:set var="message" value="Hello World"/>
	<c:set var="otherMessage" value="This is other message."/>
	<c:set var="display" value="${true}"/>
	<c:if test="${display}">
		<c:out value="${message}"></c:out>
	</c:if>
	<c:out value="${otherMessage}"></c:out>
</body>
</html>

dostaneme tuto chybu:

SEVERE: Servlet.service() for servlet [jsp] in context with path [/maven-webapp03] threw exception [/index.jsp (line: [3], column: [4]) Invalid directive] with root cause
org.apache.jasper.JasperException: /index.jsp (line: [3], column: [4]) Invalid directive

To je pochopitelné. Chceme použí tagy JSTL (Java Server Pages Standard Tag Library), ale nemáme v projektu dané knihovny. Jelikož se jedná o Maven projekt, stačí přidat závislosti do pom.xml.

		<dependency>
			<groupId>org.apache.taglibs</groupId>
			<artifactId>taglibs-standard-spec</artifactId>
			<version>1.2.5</version>
		</dependency>
		<dependency>
			<groupId>org.apache.taglibs</groupId>
			<artifactId>taglibs-standard-impl</artifactId>
			<version>1.2.5</version>
		</dependency>

Updatujeme projekt (Alt + F5) a restartujeme Tomcat. Chyba zmizela a z prohlížeče na nás kouká stránka s textem ${otherMessage} . Pokud se koukneme do zdrojového kódu (Ctrl + U), zjistíme toto:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login</title>
</head>
<body>
	
	
	
	
	${otherMessage}
</body>
</html>

Zvláštní, očekával bych dva texty („Hello World“ a „This is other message.“). Chyba je v tom, že JSTL výrazy, což je ta konstrukce „${cosi}“ se nevydnotily. Řešením je přidat do stránky direktivu <%@ page isELIgnored="false" %>. Po restartu Tomcata dostaneme konečně to, co chceme:

Hello World This is other message. 

Pokud se ale nad výše uvedeným řešením zamyslíte, určitě vám bude vrtat hlavou otázka, proč bych měl danou direktivu přidávat do každé stránky a proč to neumí by defaut. Velmi dobrá úvaha. Chyba je totiž někde jinde. Odstranili jsme následek, ale příčina zůstala a tou je web.xml. Že jste ani nevěděli, že je v projektu? Ano, je. Maven jej vygeneroval tam kam patří. Do složky WEB-INF.

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
</web-app>

Potud je vše v nejlepším pořádku. Tedy až na tu drobnost, že se jedná o starý typ deklarace. Pro JSTL je potřeba minimálně servlet verze 2.4. Pokud si tedy upravíte web.xml například následovně

<?xml version="1.0" encoding="UTF-8"?>
<web-app 
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
    version="4.0">

</web-app>

můžete klidně z jsp souboru odstranit direktivu <%@ page isELIgnored="false" %>. Vše bude fungovat jak má.

Svítí vám ve IDE varování? To je způsobeno tím, že při compilaci projektu nejsou k dispozici všechny knihovny. Jak je možné, že to ale na serveru funguje? Jednoduše proto, že na serveru tyto knihovny k dispozici jsou. Řešením je třeba přidat knihovny (celé runtime), které má server, do projektu. v Eclipse je řešení následující: pravým na projekt -> Properties -> Project Facets -> na pravé straně záložka Runtimes -> zakliknout potřebné runtime – to je pouze v případě, že v Eclipse máte server přidaný).

Řešením v případě Maven projektu je přidat knihovnu do závislosti pouze pro kompilaci.

<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>

Napsat komentář