Skip to content

Commit

Permalink
mvc-thymeleaf extension (#5616)
Browse files Browse the repository at this point in the history
Co-authored-by: Dmytro Dovnar <[email protected]>
  • Loading branch information
ddovnar and dimonmc authored Apr 30, 2024
1 parent 158c51a commit 115da13
Show file tree
Hide file tree
Showing 9 changed files with 435 additions and 0 deletions.
81 changes: 81 additions & 0 deletions ext/mvc-thymeleaf/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
http://www.eclipse.org/legal/epl-2.0.
This Source Code may also be made available under the following Secondary
Licenses when the conditions for such availability set forth in the
Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
version 2 with the GNU Classpath Exception, which is available at
https://www.gnu.org/software/classpath/license.html.
SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
-->

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<artifactId>project</artifactId>
<groupId>org.glassfish.jersey.ext</groupId>
<version>3.0.99-SNAPSHOT</version>
</parent>

<artifactId>jersey-mvc-thymeleaf</artifactId>
<name>jersey-ext-mvc-thymeleaf</name>

<description>
Jersey extension module providing support for Thymeleaf templates.
</description>

<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<inherited>true</inherited>
<extensions>true</extensions>
<configuration>
<instructions>
<Export-Package>org.glassfish.jersey.server.mvc.thymeleaf.*;version=${project.version}</Export-Package>
</instructions>
<unpackBundle>true</unpackBundle>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>${project.build.directory}/legal</directory>
</resource>
</resources>
</build>

<dependencies>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>${servlet5.version}</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-mvc</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>${thymeleaf.version}</version>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/

package org.glassfish.jersey.server.mvc.thymeleaf;

import org.thymeleaf.TemplateEngine;

public interface ThymeleafConfigurationFactory {
TemplateEngine getTemplateEngine();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/

package org.glassfish.jersey.server.mvc.thymeleaf;

import jakarta.ws.rs.core.Configuration;
import org.glassfish.jersey.internal.util.PropertiesHelper;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.messageresolver.IMessageResolver;
import org.thymeleaf.messageresolver.StandardMessageResolver;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.thymeleaf.templateresolver.ITemplateResolver;

import java.util.Map;

/**
* Handy {@link ThymeleafConfigurationFactory} that supplies a minimally
* configured {@link org.thymeleaf.TemplateEngine } able to
* render Thymeleaf templates.
* The recommended method to provide custom Thymeleaf engine settings is to
* sub-class this class, further customize the
* {@link org.thymeleaf.TemplateEngine settings} as desired in that
* class, and then register the sub-class with the {@link ThymeleafMvcFeature}
* TEMPLATE_OBJECT_FACTORY property.
*
* @author Dmytro Dovnar ([email protected])
*/
public class ThymeleafDefaultConfigurationFactory implements ThymeleafConfigurationFactory {
private final Configuration config;
private final TemplateEngine templateEngine;

public ThymeleafDefaultConfigurationFactory(Configuration config) {
this.config = config;
this.templateEngine = initTemplateEngine();
}

@Override
public TemplateEngine getTemplateEngine() {
return templateEngine;
}

private ITemplateResolver getTemplateResolver() {
Map<String, Object> properties = config.getProperties();
String basePath = (String) PropertiesHelper.getValue(properties,
"jersey.config.server.mvc.templateBasePath" + ThymeleafMvcFeature.SUFFIX,
String.class, (Map) null);
if (basePath == null) {
basePath = (String) PropertiesHelper.getValue(properties,
"jersey.config.server.mvc.templateBasePath", "", (Map) null);
}

if (basePath != null && !basePath.startsWith("/")) {
basePath = "/" + basePath;
}

String templateFileSuffix = (String) PropertiesHelper.getValue(properties,
"jersey.config.server.mvc.templateFileSuffix" + ThymeleafMvcFeature.SUFFIX,
".html", (Map) null);

String templateFileMode = (String) PropertiesHelper.getValue(properties,
"jersey.config.server.mvc.templateMode" + ThymeleafMvcFeature.SUFFIX,
"HTML5", (Map) null);

Boolean cacheEnabled = (Boolean) PropertiesHelper.getValue(properties,
"jersey.config.server.mvc.caching" + ThymeleafMvcFeature.SUFFIX, Boolean.class, (Map) null);
if (cacheEnabled == null) {
cacheEnabled = (Boolean) PropertiesHelper.getValue(properties,
"jersey.config.server.mvc.caching", false, (Map) null);
}

Long cacheLiveMs = (Long) PropertiesHelper.getValue(properties,
"jersey.config.server.mvc.cacheTTLMs" + ThymeleafMvcFeature.SUFFIX, 3600000L, (Map) null);

ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix(basePath);
templateResolver.setSuffix(templateFileSuffix);
templateResolver.setTemplateMode(templateFileMode);
templateResolver.setCacheTTLMs(cacheLiveMs);
templateResolver.setCacheable(cacheEnabled);
return templateResolver;
}

private TemplateEngine initTemplateEngine() {
TemplateEngine templateEngine = new TemplateEngine();
templateEngine.setTemplateResolver(getTemplateResolver());
return templateEngine;
}

private IMessageResolver getMessageResolver() {
StandardMessageResolver messageResolver = new StandardMessageResolver();
return messageResolver;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/

package org.glassfish.jersey.server.mvc.thymeleaf;

import jakarta.ws.rs.ConstrainedTo;
import jakarta.ws.rs.RuntimeType;
import jakarta.ws.rs.core.Configuration;
import jakarta.ws.rs.core.Feature;
import jakarta.ws.rs.core.FeatureContext;
import org.glassfish.jersey.server.mvc.MvcFeature;

@ConstrainedTo(RuntimeType.SERVER)
public final class ThymeleafMvcFeature implements Feature {
public static final String SUFFIX = ".thymeleaf";
public static final String TEMPLATE_BASE_PATH = MvcFeature.TEMPLATE_BASE_PATH + SUFFIX;
public static final String CACHE_TEMPLATES = MvcFeature.CACHE_TEMPLATES + SUFFIX;
public static final String TEMPLATE_OBJECT_FACTORY = MvcFeature.TEMPLATE_OBJECT_FACTORY + SUFFIX;
public static final String ENCODING = MvcFeature.ENCODING + SUFFIX;

public static final String TEMPLATE_FILE_SUFFIX = "jersey.config.server.mvc.templateFileSuffix" + SUFFIX;
public static final String TEMPLATE_MODE = "jersey.config.server.mvc.templateMode" + SUFFIX;
public static final String CACHE_TTLMS = "jersey.config.server.mvc.cacheTTLMs" + SUFFIX;

@Override
public boolean configure(FeatureContext context) {
final Configuration config = context.getConfiguration();

if (!config.isRegistered(ThymeleafViewProcessor.class)) {
context.register(ThymeleafViewProcessor.class);

// MvcFeature.
if (!config.isRegistered(MvcFeature.class)) {
context.register(MvcFeature.class);
}

return true;
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/

package org.glassfish.jersey.server.mvc.thymeleaf;

import org.thymeleaf.TemplateEngine;

/**
* {@link ThymeleafConfigurationFactory} that supplies an unchanged
* {@link ThymeleafConfigurationFactory Configuration} as passed-in to
* the constructor.
* <p/>
* Used to support backwards-compatibility in {@link ThymeleafViewProcessor}
* to wrap directly-configured {@link org.thymeleaf.TemplateEngine}
* objects instead of the recommended {@link ThymeleafDefaultConfigurationFactory}
* or a sub-class thereof.
*
* @author Dmytro Dovnar ([email protected])
*/
public class ThymeleafSuppliedConfigurationFactory implements ThymeleafConfigurationFactory {
private final ThymeleafConfigurationFactory configurationFactory;

public ThymeleafSuppliedConfigurationFactory(ThymeleafConfigurationFactory configurationFactory) {
this.configurationFactory = configurationFactory;
}

@Override
public TemplateEngine getTemplateEngine() {
return configurationFactory.getTemplateEngine();
}

}
Loading

0 comments on commit 115da13

Please sign in to comment.