[JAVA] Enable WebJars for blank projects in TERASOLUNA 5.x (= Spring MVC)

This time, in the development project generated from the blank project provided by TERASOLUNA 5.x (= Spring Framework), the file of the client library (CSS library, JS library) is applied by using the mechanism of WebJars. I will show you how to incorporate it into (= make a note).

Waht's TERASOLUNA 5.x ?

You can find out who TERASOLUNA 5.x is here here. It's a pity that the configuration method is XML-based and does not support Spring Boot, but it is packed with know-how for developing web applications using Spring, and maintenance is continuous (once a year). It is done in minor version upgrade + α).

Verification version

Generation of development project

In TERASOLUNA 5.x, "single project configuration" and "multi-project (multi-module) configuration We provide two types of blank projects (Mavne Archetype) of "/ terasolunaorg / terasoluna-gfw-web-multi-blank)", but this time we will create a project with a single project configuration.

command


$ mvn archetype:generate -B\
 -DarchetypeGroupId=org.terasoluna.gfw.blank\
 -DarchetypeArtifactId=terasoluna-gfw-web-blank-archetype\
 -DarchetypeVersion=5.3.0.RELEASE\
 -DgroupId=com.example\
 -DartifactId=demo-webjars\
 -Dversion=1.0.0-SNAPSHOT

Command execution result


$ mvn archetype:generate -B\
>  -DarchetypeGroupId=org.terasoluna.gfw.blank\
>  -DarchetypeArtifactId=terasoluna-gfw-web-blank-archetype\
>  -DarchetypeVersion=5.3.0.RELEASE\
>  -DgroupId=com.example\
>  -DartifactId=demo-webjars\
>  -Dversion=1.0.0-SNAPSHOT
[INFO] Scanning for projects...
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] >>> maven-archetype-plugin:2.3:generate (default-cli) > generate-sources @ standalone-pom >>>
[INFO] 
[INFO] <<< maven-archetype-plugin:2.3:generate (default-cli) < generate-sources @ standalone-pom <<<
[INFO] 
[INFO] 
[INFO] --- maven-archetype-plugin:2.3:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Batch mode
[INFO] Archetype repository not defined. Using the one from [org.terasoluna.gfw.blank:terasoluna-gfw-web-blank-archetype:5.3.0.RELEASE] found in catalog remote
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: terasoluna-gfw-web-blank-archetype:5.3.0.RELEASE
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.example
[INFO] Parameter: artifactId, Value: demo-webjars
[INFO] Parameter: version, Value: 1.0.0-SNAPSHOT
[INFO] Parameter: package, Value: com.example
[INFO] Parameter: packageInPathFormat, Value: com/example
[INFO] Parameter: package, Value: com.example
[INFO] Parameter: version, Value: 1.0.0-SNAPSHOT
[INFO] Parameter: groupId, Value: com.example
[INFO] Parameter: artifactId, Value: demo-webjars
[INFO] project created from Archetype in dir: /usr/local/apps/demo-webjars
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.617 s
[INFO] Finished at: 2017-09-03T13:01:31+09:00
[INFO] Final Memory: 16M/222M
[INFO] ------------------------------------------------------------------------
$

Configuration in the project


$ tree demo-webjars
demo-webjars
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── example
    │   │           ├── app
    │   │           │   └── welcome
    │   │           │       └── HelloController.java
    │   │           └── domain
    │   │               ├── model
    │   │               ├── repository
    │   │               └── service
    │   ├── resources
    │   │   ├── META-INF
    │   │   │   ├── dozer
    │   │   │   └── spring
    │   │   │       ├── applicationContext.xml
    │   │   │       ├── demo-webjars-codelist.xml
    │   │   │       ├── demo-webjars-domain.xml
    │   │   │       ├── demo-webjars-infra.xml
    │   │   │       ├── spring-mvc.xml
    │   │   │       └── spring-security.xml
    │   │   ├── ValidationMessages.properties
    │   │   ├── dozer.properties
    │   │   ├── i18n
    │   │   │   └── application-messages.properties
    │   │   └── logback.xml
    │   └── webapp
    │       ├── WEB-INF
    │       │   ├── views
    │       │   │   ├── common
    │       │   │   │   ├── error
    │       │   │   │   │   ├── accessDeniedError.jsp
    │       │   │   │   │   ├── businessError.jsp
    │       │   │   │   │   ├── dataAccessError.jsp
    │       │   │   │   │   ├── invalidCsrfTokenError.jsp
    │       │   │   │   │   ├── missingCsrfTokenError.jsp
    │       │   │   │   │   ├── resourceNotFoundError.jsp
    │       │   │   │   │   ├── systemError.jsp
    │       │   │   │   │   ├── transactionTokenError.jsp
    │       │   │   │   │   └── unhandledSystemError.html
    │       │   │   │   └── include.jsp
    │       │   │   └── welcome
    │       │   │       └── home.jsp
    │       │   └── web.xml
    │       └── resources
    │           └── app
    │               └── css
    │                   └── styles.css
    └── test
        ├── java
        └── resources

28 directories, 25 files
$ 

Build the project

After creating the project, use the Mavne command to build the war file.

$ cd demo-webjars
$ mvn package
[INFO] Scanning for projects...
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] Building TERASOLUNA Server Framework for Java (5.x) Web Blank Project 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ demo-webjars ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 11 resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ demo-webjars ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /usr/local/apps/demo-webjars/target/classes
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ demo-webjars ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ demo-webjars ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ demo-webjars ---
[INFO] 
[INFO] --- maven-war-plugin:2.5:war (default-war) @ demo-webjars ---
[INFO] Packaging webapp
[INFO] Assembling webapp [demo-webjars] in [/usr/local/apps/demo-webjars/target/demo-webjars-1.0.0-SNAPSHOT]
[INFO] Processing war project
[INFO] Copying webapp resources [/usr/local/apps/demo-webjars/src/main/webapp]
[INFO] Webapp assembled in [324 msecs]
[INFO] Building war: /usr/local/apps/demo-webjars/target/demo-webjars.war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.454 s
[INFO] Finished at: 2017-09-03T13:07:22+09:00
[INFO] Final Memory: 32M/258M
[INFO] ------------------------------------------------------------------------
$

Launch web app

Deploy the built war file to the application server (Tomcat) using the Carog Mavne Plugin and start it.

$ mvn cargo:run
[INFO] Scanning for projects...
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] Building TERASOLUNA Server Framework for Java (5.x) Web Blank Project 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- cargo-maven2-plugin:1.6.2:run (default-cli) @ demo-webjars ---
[INFO] [en2.ContainerRunMojo] Resolved container artifact org.codehaus.cargo:cargo-core-container-tomcat:jar:1.6.2 for container tomcat8x
[INFO] [talledLocalContainer] Tomcat 8.x starting...
[INFO] [stalledLocalDeployer] Deploying [/usr/local/apps/demo-webjars/target/demo-webjars.war] to [/usr/local/apps/demo-webjars/target/cargo/configurations/tomcat8x/webapps]...
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.startup.VersionLoggerListener log
[INFO] [talledLocalContainer]information: Server version:        Apache Tomcat/8.0.39
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.startup.VersionLoggerListener log
[INFO] [talledLocalContainer]information: Server built:          Nov 9 2016 08:48:39 UTC
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.startup.VersionLoggerListener log
[INFO] [talledLocalContainer]information: Server number:         8.0.39.0
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.startup.VersionLoggerListener log
[INFO] [talledLocalContainer]information: OS Name:               Mac OS X
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.startup.VersionLoggerListener log
[INFO] [talledLocalContainer]information: OS Version:            10.10.5
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.startup.VersionLoggerListener log
[INFO] [talledLocalContainer]information: Architecture:          x86_64
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.startup.VersionLoggerListener log
[INFO] [talledLocalContainer]information: Java Home:             /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.startup.VersionLoggerListener log
[INFO] [talledLocalContainer]information: JVM Version:           1.8.0_131-b11
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.startup.VersionLoggerListener log
[INFO] [talledLocalContainer]information: JVM Vendor:            Oracle Corporation
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.startup.VersionLoggerListener log
[INFO] [talledLocalContainer]information: CATALINA_BASE:         /usr/local/apps/demo-webjars/target/cargo/configurations/tomcat8x
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.startup.VersionLoggerListener log
[INFO] [talledLocalContainer]information: CATALINA_HOME:         /usr/local/apps/demo-webjars/target/cargo/installs/apache-tomcat-8.0.39/apache-tomcat-8.0.39
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.startup.VersionLoggerListener log
[INFO] [talledLocalContainer]information: Command line argument: -Xms512m
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.startup.VersionLoggerListener log
[INFO] [talledLocalContainer]information: Command line argument: -Xmx1024m
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.startup.VersionLoggerListener log
[INFO] [talledLocalContainer]information: Command line argument: -Dcatalina.home=/usr/local/apps/demo-webjars/target/cargo/installs/apache-tomcat-8.0.39/apache-tomcat-8.0.39
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.startup.VersionLoggerListener log
[INFO] [talledLocalContainer]information: Command line argument: -Dcatalina.base=/usr/local/apps/demo-webjars/target/cargo/configurations/tomcat8x
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.startup.VersionLoggerListener log
[INFO] [talledLocalContainer]information: Command line argument: -Djava.io.tmpdir=/usr/local/apps/demo-webjars/target/cargo/configurations/tomcat8x/temp
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.startup.VersionLoggerListener log
[INFO] [talledLocalContainer]information: Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.startup.VersionLoggerListener log
[INFO] [talledLocalContainer]information: Command line argument: -Djava.util.logging.config.file=/usr/local/apps/demo-webjars/target/cargo/configurations/tomcat8x/conf/logging.properties
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.core.AprLifecycleListener lifecycleEvent
[INFO] [talledLocalContainer]information: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /Users/shimizukazuki/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.coyote.AbstractProtocol init
[INFO] [talledLocalContainer]information: Initializing ProtocolHandler ["http-nio-8080"]
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.tomcat.util.net.NioSelectorPool getSharedSelector
[INFO] [talledLocalContainer]information: Using a shared selector for servlet write/read
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.coyote.AbstractProtocol init
[INFO] [talledLocalContainer]information: Initializing ProtocolHandler ["ajp-nio-8009"]
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.tomcat.util.net.NioSelectorPool getSharedSelector
[INFO] [talledLocalContainer]information: Using a shared selector for servlet write/read
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.startup.Catalina load
[INFO] [talledLocalContainer]information: Initialization processed in 595 ms
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.core.StandardService startInternal
[INFO] [talledLocalContainer]information:Start the service Catalina
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.core.StandardEngine startInternal
[INFO] [talledLocalContainer]information: Starting Servlet Engine: Apache Tomcat/8.0.39
[INFO] [talledLocalContainer] 9 03, 2017 1:08:56 pm org.apache.catalina.startup.HostConfig deployWAR
[INFO] [talledLocalContainer]information:Web application archive/usr/local/apps/demo-webjars/target/cargo/configurations/tomcat8x/webapps/cargocpc.Deploy war
[INFO] [talledLocalContainer] 9 03, 2017 1:08:57 pm org.apache.catalina.startup.HostConfig deployWAR
[INFO] [talledLocalContainer]information: Deployment of web application archive /usr/local/apps/demo-webjars/target/cargo/configurations/tomcat8x/webapps/cargocpc.war has finished in 295 ms
[INFO] [talledLocalContainer] 9 03, 2017 1:08:57 pm org.apache.catalina.startup.HostConfig deployWAR
[INFO] [talledLocalContainer]information:Web application archive/usr/local/apps/demo-webjars/target/cargo/configurations/tomcat8x/webapps/demo-webjars.Deploy war
[INFO] [talledLocalContainer] 9 03, 2017 1:08:58 pm org.apache.jasper.servlet.TldScanner scanJars
[INFO] [talledLocalContainer]information: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
[INFO] [talledLocalContainer] 9 03, 2017 1:08:58 pm org.apache.catalina.core.ApplicationContext log
[INFO] [talledLocalContainer]information: No Spring WebApplicationInitializer types detected on classpath
[INFO] [talledLocalContainer] 9 03, 2017 1:08:59 pm org.apache.catalina.core.ApplicationContext log
[INFO] [talledLocalContainer]information: Initializing Spring root WebApplicationContext
[INFO] [talledLocalContainer] 9 03, 2017 1:09:00 pm org.apache.catalina.core.ApplicationContext log
[INFO] [talledLocalContainer]information: Initializing Spring FrameworkServlet 'appServlet'
[INFO] [talledLocalContainer] date:2017-09-03 13:09:00	thread:localhost-startStop-1	X-Track:	level:INFO 	logger:o.springframework.web.servlet.DispatcherServlet 	message:FrameworkServlet 'appServlet': initialization started
[INFO] [talledLocalContainer] date:2017-09-03 13:09:00	thread:localhost-startStop-1	X-Track:	level:INFO 	logger:o.s.w.s.m.m.a.RequestMappingHandlerMapping      	message:Mapped "{[/],methods=[GET || POST]}" onto public java.lang.String com.example.app.welcome.HelloController.home(java.util.Locale,org.springframework.ui.Model)
[INFO] [talledLocalContainer] date:2017-09-03 13:09:01	thread:localhost-startStop-1	X-Track:	level:INFO 	logger:o.s.w.s.m.m.a.RequestMappingHandlerAdapter      	message:Looking for @ControllerAdvice: WebApplicationContext for namespace 'appServlet-servlet': startup date [Sun Sep 03 13:09:00 JST 2017]; parent: Root WebApplicationContext
[INFO] [talledLocalContainer] date:2017-09-03 13:09:01	thread:localhost-startStop-1	X-Track:	level:INFO 	logger:o.s.w.s.m.m.a.RequestMappingHandlerAdapter      	message:Looking for @ControllerAdvice: WebApplicationContext for namespace 'appServlet-servlet': startup date [Sun Sep 03 13:09:00 JST 2017]; parent: Root WebApplicationContext
[INFO] [talledLocalContainer] date:2017-09-03 13:09:01	thread:localhost-startStop-1	X-Track:	level:INFO 	logger:o.s.web.servlet.handler.SimpleUrlHandlerMapping 	message:Mapped URL path [/**] onto handler 'org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler#0'
[INFO] [talledLocalContainer] date:2017-09-03 13:09:01	thread:localhost-startStop-1	X-Track:	level:INFO 	logger:o.s.web.servlet.handler.SimpleUrlHandlerMapping 	message:Mapped URL path [/resources/**] onto handler 'org.springframework.web.servlet.resource.ResourceHttpRequestHandler#0'
[INFO] [talledLocalContainer] date:2017-09-03 13:09:01	thread:localhost-startStop-1	X-Track:	level:INFO 	logger:o.springframework.web.servlet.DispatcherServlet 	message:FrameworkServlet 'appServlet': initialization completed in 1222 ms
[INFO] [talledLocalContainer] 9 03, 2017 1:09:01 pm org.apache.catalina.startup.HostConfig deployWAR
[INFO] [talledLocalContainer]information: Deployment of web application archive /usr/local/apps/demo-webjars/target/cargo/configurations/tomcat8x/webapps/demo-webjars.war has finished in 4,615 ms
[INFO] [talledLocalContainer] 9 03, 2017 1:09:01 pm org.apache.catalina.startup.HostConfig deployDirectory
[INFO] [talledLocalContainer]information:Web application directory/usr/local/apps/demo-webjars/target/cargo/configurations/tomcat8x/webapps/host-Deploy manager
[INFO] [talledLocalContainer] 9 03, 2017 1:09:01 pm org.apache.catalina.startup.HostConfig deployDirectory
[INFO] [talledLocalContainer]information: Deployment of web application directory /usr/local/apps/demo-webjars/target/cargo/configurations/tomcat8x/webapps/host-manager has finished in 19 ms
[INFO] [talledLocalContainer] 9 03, 2017 1:09:01 pm org.apache.catalina.startup.HostConfig deployDirectory
[INFO] [talledLocalContainer]information:Web application directory/usr/local/apps/demo-webjars/target/cargo/configurations/tomcat8x/webapps/Deploy manager
[INFO] [talledLocalContainer] 9 03, 2017 1:09:01 pm org.apache.catalina.startup.HostConfig deployDirectory
[INFO] [talledLocalContainer]information: Deployment of web application directory /usr/local/apps/demo-webjars/target/cargo/configurations/tomcat8x/webapps/manager has finished in 12 ms
[INFO] [talledLocalContainer] 9 03, 2017 1:09:01 pm org.apache.coyote.AbstractProtocol start
[INFO] [talledLocalContainer]information: Starting ProtocolHandler ["http-nio-8080"]
[INFO] [talledLocalContainer] 9 03, 2017 1:09:01 pm org.apache.coyote.AbstractProtocol start
[INFO] [talledLocalContainer]information: Starting ProtocolHandler ["ajp-nio-8009"]
[INFO] [talledLocalContainer] 9 03, 2017 1:09:01 pm org.apache.catalina.startup.Catalina start
[INFO] [talledLocalContainer]information: Server startup in 5012 ms
[INFO] [talledLocalContainer] Tomcat 8.x started on port [8080]
[INFO] Press Ctrl-C to stop the container...

When you access the application root, the following top screen (HTML) is applied.

$ curl -D - http://localhost:8080/demo-webjars/
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Track: c061e8853a3f49c2919c8ac6f46071cf
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Content-Type: text/html;charset=UTF-8
Content-Language: ja-JP
Content-Length: 320
Date: Sun, 03 Sep 2017 04:11:03 GMT









<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Home</title>
<link rel="stylesheet"
    href="/demo-webjars/resources/app/css/styles.css">
</head>
<body>
    <div id="wrapper">
        <h1>Hello world!</h1>
        <p>The time on the server is 2017/09/03 13:11:03 JST.</p>
    </div>
</body>
</html>
$

Use WebJars

This time, I will try to incorporate the CSS library Bootstrap into the application using the mechanism of WebJars.

pom.xml


<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>bootstrap</artifactId>
    <version>3.3.7-1</version>
</dependency>

Rebuild the war and deploy / start it again.

$ mvn package cargo:run
...
$

Try accessing the webJars bootstrap css file.

$ curl -D - http://localhost:8080/demo-webjars/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Track: cda63d914b0142c5bd36c0e85dd8e22d
Accept-Ranges: bytes
ETag: W/"121200-1469407916000"
Last-Modified: Mon, 25 Jul 2016 00:51:56 GMT
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Content-Type: text/css;charset=UTF-8
Content-Length: 121200
Date: Sun, 03 Sep 2017 04:24:44 GMT

/*!
 * Bootstrap v3.3.7 (http://getbootstrap.com)
 * Copyright 2011-2016 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{fo....
...

For application servers that support Servlet 3.0+, if there is a WebJars jar file in the classpath (WEB-INF / lib, etc.), you can access it without any special settings.

So, if you just use WebJars,

src/main/webapp/WEB-INF/views/welcome/home.jsp


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Home</title>
<link rel="stylesheet"
    href="${pageContext.request.contextPath}/resources/app/css/styles.css">
<link rel="stylesheet"
      href="${pageContext.request.contextPath}/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css"> <!--★ Addition-->
</head>
<body>
    <div id="wrapper">
        <h1>Hello world!</h1>
        <p>The time on the server is ${serverTime}.</p>
    </div>
</body>
</html>

If so, it's OK.

Eliminate version numbers using webjar-locator

Perhaps ... many engineers don't want to include the version number (3.3.7-1 in this example) in the URL when accessing the css file. Spring MVC provides a mechanism to exclude the version number from application code (JSP etc.) by linking with a library called webjar-locator.

pon.xml


<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>webjars-locator</artifactId>
</dependency>

src/main/resources/META-INF/spring/spring-mvc.xml


<mvc:resources mapping="/webjars/**" location="/webjars/">
    <mvc:resource-chain resource-cache="true"/> <!--If you specify this tag, Spring will be webjars-Automatically activates the function of linking with locator-->
</mvc:resources>

Rebuild the war, deploy and start it again, remove the version number and try to access it.

$ curl -D - http://localhost:8080/demo-webjars/webjars/bootstrap/css/bootstrap.min.css
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Track: adb21119739e422bb3faf020ff5e9e3f
Last-Modified: Sat, 17 Sep 2016 02:28:22 GMT
Accept-Ranges: bytes
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Content-Type: text/css;charset=UTF-8
Content-Length: 121200
Date: Sun, 03 Sep 2017 04:53:18 GMT

/*!
 * Bootstrap v3.3.7 (http://getbootstrap.com)
 * Copyright 2011-2016 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{
...

You could access it.

So, the part that specifies the css file to read is ...

src/main/webapp/WEB-INF/views/welcome/home.jsp


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Home</title>
<link rel="stylesheet"
    href="${pageContext.request.contextPath}/resources/app/css/styles.css">
<link rel="stylesheet"
      href="${pageContext.request.contextPath}/webjars/bootstrap/css/bootstrap.min.css"> <!--★ Remove version number from path-->
</head>
<body>
    <div id="wrapper">
        <h1>Hello world!</h1>
        <p>The time on the server is ${serverTime}.</p>
    </div>
</body>
</html>

If so, it's OK.

Take measures against browser cache when upgrading

The fact that you don't need to include the version number in the path means that the path doesn't change even if you increase the version of the library. This means that depending on the Cache-Control settings, the files cached by the browser (files before version upgrade) may be used. However, if these files are not cached, useless network traffic and resource access on the server side will occur, so it is expected that "the load on the system will increase" and "the screen drawing speed will slow down". ..

To solve this problem

You can do it ... how (properly) ... Spring provides this feature! !!

First, register the ResourceUrlEncodingFilter provided by Spring as a Servlet filter.

** Important: Servlet filter definition order **

Define ** after ** after the Spring Security Servlet Filter (springSecurityFilterChain).

src/main/webapp/WEB-INF/web.xml


<filter>
    <filter-name>ResourceUrlEncodingFilter</filter-name>
    <filter-class>org.springframework.web.servlet.resource.ResourceUrlEncodingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>ResourceUrlEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Therefore, JSP uses the tag library provided by JSTL or Spring when specifying the path.

src/main/webapp/WEB-INF/views/welcome/home.jsp


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Home</title>
<link rel="stylesheet"
    href="${pageContext.request.contextPath}/resources/app/css/styles.css">
<link rel="stylesheet"
      href="${pageContext.request.contextPath}/webjars/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet"
      href="<c:url value='/webjars/bootstrap/css/bootstrap.min.css'/>"> <!--★ Use JSTL tag library-->
<link rel="stylesheet"
      href="<spring:url value='/webjars/bootstrap/css/bootstrap.min.css'/>"> <!--★ Use Spring tag library-->
</head>
<body>
    <div id="wrapper">
        <h1>Hello world!</h1>
        <p>The time on the server is ${serverTime}.</p>
    </div>
</body>
</html>

Then ...

$ curl -D - http://localhost:8080/demo-webjars/
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Track: 5576191e3ed54e82a83b67236bc98b24
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Content-Type: text/html;charset=UTF-8
Content-Language: ja-JP
Content-Length: 609
Date: Sun, 03 Sep 2017 05:28:08 GMT









<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Home</title>
<link rel="stylesheet"
    href="/demo-webjars/resources/app/css/styles.css">
<link rel="stylesheet"
      href="/demo-webjars/webjars/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet"
      href="/demo-webjars/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css">
<link rel="stylesheet"
      href="/demo-webjars/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css">
</head>
<body>
    <div id="wrapper">
        <h1>Hello world!</h1>
        <p>The time on the server is 2017/09/03 14:28:08 JST.</p>
    </div>
</body>
</html>
$

HTML generated from JSP now includes the version number in the path.

Take measures against browser cache

Blank projects in TERASOLUNA 5.x provide Spring Security Servlet filters by default and are set to not cache access to paths other than / resources / **. In other words, access to / webjars / ** is not cached, so you will have to re-acquire the CSS file each time you draw the screen.

To change this behavior, you can exclude access to / webjars / ** from Spring Security processing.

src/main/resources/META-INF/spring/spring-security.xml


<sec:http pattern="/resources/**" security="none"/>
<sec:http pattern="/webjars/**" security="none"/> <!--★ Addition-->
<sec:http>
    <!-- ... -->
</sec:http>

If you access in this state ...

$ curl -D - http://localhost:8080/demo-webjars/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Track: a27dba531c8f4c79af0657ceaf5b430b
Last-Modified: Sat, 17 Sep 2016 02:28:22 GMT
Accept-Ranges: bytes
Content-Type: text/css;charset=UTF-8
Content-Length: 121200
Date: Sun, 03 Sep 2017 05:48:20 GMT

/*!
 * Bootstrap v3.3.7 (http://getbootstrap.com)
 * Copyright 2011-2016 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{...
...

You can see that the Cache-Control header that Spring Security has given is gone. When I checked with Chrome and Safari,

It was a feeling that it was moving. (It may be a lie ...)

Exclude from the processing target of HanderInterceptor

In the TERASOLUNA 5.x blank project, the following HandlerInterceptor is applied by default, so prevent it from being applied when retrieving resources from WebJars.

src/main/resources/META-INF/spring/spring-mvc.xml


<mvc:interceptor>
    <mvc:mapping path="/**" />
    <mvc:exclude-mapping path="/resources/**" />
    <mvc:exclude-mapping path="/webjars/**" /> <!--★ Addition-->
    <mvc:exclude-mapping path="/**/*.html" />
    <bean
        class="org.terasoluna.gfw.web.logging.TraceLoggingInterceptor" />
</mvc:interceptor>

Summary

With WebJars,

Because there is a merit, I would like to use it positively.

Reference site

Recommended Posts

Enable WebJars for blank projects in TERASOLUNA 5.x (= Spring MVC)
How to realize huge file upload with TERASOLUNA 5.x (= Spring MVC)
[Java Spring MVC] Controller for development confirmation
Enable code completion in Eclipse for Mac
How Dispatcher servlet works in Spring MVC