Skip to content

feat: support spring framework 6 spring boot 3 #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 49 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Spring Configuration
</property>
</bean>



Localization Support
---------------
Expand All @@ -72,8 +72,55 @@ Localization Support
<bean id="i18nMessageInterceptor" class="org.springframework.web.servlet.view.mustache.jmustache.LocalizationMessageInterceptor">
<property name="localeResolver" ref="..." />
</bean>

Spring Boot 3 - Configuration
-------------
Once you have a spring boot 3 web application running, register the mustache spring view dependency via the pom.xml:
```
<dependency>
<groupId>com.github.sps.mustache</groupId>
<artifactId>mustache-spring-view</artifactId>
<version>1.5-SNAPSHOT</version>
</dependency>
```
Create the localization implementation for mustache i18n lambda
```
public class LocalizationMessageInterceptor extends MustacheLocalizationMessageInterceptor {
public LocalizationMessageInterceptor() {
}

protected Object createHelper(final HttpServletRequest request) {
return new Mustache.Lambda() {
public void execute(Template.Fragment frag, Writer out) throws IOException {
LocalizationMessageInterceptor.this.localize(request, frag.execute(), out);
}
};
}
}
```
Register the localization implementation
```
@Component
public class InterceptorRegistration implements WebMvcConfigurer {
@Autowired
LocalizationMessageInterceptor localizationMessageInterceptor;

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localizationMessageInterceptor);
}
}
```
Ensure to add your `messages.properties` files in your application.yaml:
```
spring:
messages:
basename: "messages.error.messages,messages.business.messages"
```
This means: having a directory `messages` containing `error` and `business` directory, having messages bundle within it (messages.properties messages_uk.
properties etc)


Thanks
---------------
Thanks to [Eric White](https://github.com/ericdwhite) for [forking](https://github.com/ericdwhite/mustache.java-spring-webmvc/) this code base and providing the mustache.java implementation.
Thanks to [Eric White](https://github.com/ericdwhite) for [forking](https://github.com/ericdwhite/mustache.java-spring-webmvc/) this code base and providing the mustache.java implementation.
81 changes: 51 additions & 30 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@
</developer>
</developers>
<properties>
<org.springframework.version>4.0.3.RELEASE</org.springframework.version>
<jmustache.version>1.9</jmustache.version>
<mustache.java.version>0.8.14</mustache.java.version>
<mockito.version>1.9.0</mockito.version>
<junit.version>4.11</junit.version>
<jdk.version>1.5</jdk.version>
<org.springframework.version>6.0.2</org.springframework.version>
<jmustache.version>1.15</jmustache.version>
<mustache.java.version>0.9.10</mustache.java.version>
<mockito.version>4.9.0</mockito.version>
<junit.version>4.13.2</junit.version>
<jdk.version>17</jdk.version>
</properties>
<profiles>
<profile>
Expand All @@ -56,7 +56,7 @@
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<version>3.10.1</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
Expand All @@ -80,27 +80,48 @@
</execution>
</executions>
</plugin>
<!-- New errors due to running spotbug.... -->
<!-- [ERROR] Medium: org.springframework.web.servlet.i18n.MustacheLocalizationMessageInterceptor.setLocaleResolver(LocaleResolver) may expose internal representation by storing an externally mutable object into MustacheLocalizationMessageInterceptor.localeResolver [org.springframework.web.servlet.i18n.MustacheLocalizationMessageInterceptor] At MustacheLocalizationMessageInterceptor.java:[line 120] EI_EXPOSE_REP2-->
<!-- [ERROR] Medium: Non-null field localeResolver is not initialized by new org.springframework.web.servlet.i18n.MustacheLocalizationMessageInterceptor() [org.springframework.web.servlet.i18n.MustacheLocalizationMessageInterceptor] At MustacheLocalizationMessageInterceptor.java:[lines 40-49] NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR-->
<!-- [ERROR] Medium: Non-null field messageSource is not initialized by new org.springframework.web.servlet.i18n.MustacheLocalizationMessageInterceptor() [org.springframework.web.servlet.i18n.MustacheLocalizationMessageInterceptor] At MustacheLocalizationMessageInterceptor.java:[lines 40-49] NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR-->
<!-- [ERROR] Medium: new org.springframework.web.servlet.view.mustache.MustacheViewResolver(MustacheTemplateFactory) may expose internal representation by storing an externally mutable object into MustacheViewResolver.templateFactory [org.springframework.web.servlet.view.mustache.MustacheViewResolver] At MustacheViewResolver.java:[line 30] EI_EXPOSE_REP2-->
<!-- [ERROR] Medium: new org.springframework.web.servlet.view.mustache.java.MustacheJTemplate(Mustache) may expose internal representation by storing an externally mutable object into MustacheJTemplate.template [org.springframework.web.servlet.view.mustache.java.MustacheJTemplate] At MustacheJTemplate.java:[line 29] EI_EXPOSE_REP2-->
<!-- [ERROR] Medium: org.springframework.web.servlet.view.mustache.jmustache.JMustacheTemplateFactory.setTemplateLoader(JMustacheTemplateLoader) may expose internal representation by storing an externally mutable object into JMustacheTemplateFactory.templateLoader [org.springframework.web.servlet.view.mustache.jmustache.JMustacheTemplateFactory] At JMustacheTemplateFactory.java:[line 71] EI_EXPOSE_REP2-->
<!-- [INFO]-->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>3.0.4</version>
<configuration>
<effort>Max</effort>
<threshold>Default</threshold>
<xmlOutput>true</xmlOutput>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<version>4.7.3.0</version>
<dependencies>
<!-- overwrite dependency on spotbugs if you want to specify the version of spotbugs -->
<dependency>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs</artifactId>
<version>4.7.3</version>
</dependency>
</dependencies>
</plugin>
<!-- <plugin>-->
<!-- <groupId>org.codehaus.mojo</groupId>-->
<!-- <artifactId>findbugs-maven-plugin</artifactId>-->
<!-- <version>3.0.4</version>-->
<!-- <configuration>-->
<!-- <effort>Max</effort>-->
<!-- <threshold>Default</threshold>-->
<!-- <xmlOutput>true</xmlOutput>-->
<!-- </configuration>-->
<!-- <executions>-->
<!-- <execution>-->
<!-- <goals>-->
<!-- <goal>check</goal>-->
<!-- </goals>-->
<!-- </execution>-->
<!-- </executions>-->
<!-- </plugin>-->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.0.201403182114</version>
<version>0.8.8</version>
<executions>
<execution>
<id>default-prepare-agent</id>
Expand All @@ -122,11 +143,11 @@
</goals>
<configuration>
<rules>
<!-- implmentation is needed only for Maven 2 -->
<!-- implementation is needed only for Maven 2 -->
<rule implementation="org.jacoco.maven.RuleConfiguration">
<element>BUNDLE</element>
<limits>
<!-- implmentation is needed only for Maven 2 -->
<!-- implementation is needed only for Maven 2 -->
<limit implementation="org.jacoco.report.check.Limit">
<counter>COMPLEXITY</counter>
<value>COVEREDRATIO</value>
Expand Down Expand Up @@ -201,14 +222,14 @@
<scope>provided</scope>
</dependency>


<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>


<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand All @@ -230,4 +251,4 @@
</dependency>

</dependencies>
</project>
</project>
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/*
* Copyright 2012 the original author or authors.
*
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
Expand All @@ -15,14 +15,14 @@
*/
package org.springframework.web.servlet.i18n;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
Expand All @@ -37,25 +37,19 @@
* <p/>
* e.g. {{#i18n}}labels.global.mustache [arg1]...[argN]{{/i18n}}
*/
public abstract class MustacheLocalizationMessageInterceptor extends HandlerInterceptorAdapter implements
MessageSourceAware {

public abstract class MustacheLocalizationMessageInterceptor implements HandlerInterceptor, MessageSourceAware {
/**
* Default key to be used in message templates.
* <p/>
* e.g. {{i18n}}internationalize.this.key.please{{/i18n}}
*/
public static final String DEFAULT_MODEL_KEY = "i18n";

private static final Pattern KEY_PATTERN = Pattern.compile("(.*?)[\\s\\[]");
private static final Pattern ARGS_PATTERN = Pattern.compile("\\[(.*?)\\]");

private String messageKey = DEFAULT_MODEL_KEY;

private MessageSource messageSource;
private LocaleResolver localeResolver;


protected final void localize(final HttpServletRequest request, String frag, Writer out) throws IOException {
final Locale locale = localeResolver.resolveLocale(request);
final String key = extractKey(frag);
Expand All @@ -66,19 +60,13 @@ protected final void localize(final HttpServletRequest request, String frag, Wri

protected abstract Object createHelper(final HttpServletRequest request);

@Override
public void postHandle(final HttpServletRequest request, final HttpServletResponse response,
final Object handler,
final ModelAndView modelAndView) throws Exception {

public void postHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler, final ModelAndView modelAndView) throws Exception {
if (modelAndView != null) {
modelAndView.addObject(messageKey, createHelper(request));
}

super.postHandle(request, response, handler, modelAndView);
}


/**
* Split key from (optional) arguments.
*
Expand All @@ -90,7 +78,6 @@ private String extractKey(String key) {
if (matcher.find()) {
return matcher.group(1);
}

return key;
}

Expand Down Expand Up @@ -132,6 +119,4 @@ public void setMessageSource(MessageSource messageSource) {
public void setLocaleResolver(LocaleResolver localeResolver) {
this.localeResolver = localeResolver;
}


}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,18 @@
*/
package org.springframework.web.servlet.view.mustache;

import com.samskivert.mustache.Template;
import org.springframework.web.servlet.view.AbstractTemplateView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Writer;
import java.util.Map;

/**
* @author Sean Scanlon <[email protected]>
*/
public class MustacheView extends AbstractTemplateView {

private MustacheTemplate template;

@Override
protected void renderMergedTemplateModel(Map<String, Object> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {

protected void renderMergedTemplateModel(Map<String, Object> model, final jakarta.servlet.http.HttpServletRequest request, final jakarta.servlet.http.HttpServletResponse response) throws Exception {
response.setContentType(getContentType());
final Writer writer = response.getWriter();
template.execute(model, writer);
Expand All @@ -47,4 +40,5 @@ public void setTemplate(MustacheTemplate template) {
public MustacheTemplate getTemplate() {
return template;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/
package org.springframework.web.servlet.view.mustache;

import org.springframework.beans.factory.annotation.Required;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.AbstractTemplateViewResolver;
import org.springframework.web.servlet.view.AbstractUrlBasedView;
Expand All @@ -25,9 +24,10 @@
*/
public class MustacheViewResolver extends AbstractTemplateViewResolver implements ViewResolver {

private MustacheTemplateFactory templateFactory;
private final MustacheTemplateFactory templateFactory;

public MustacheViewResolver() {
public MustacheViewResolver(final MustacheTemplateFactory templateFactory) {
this.templateFactory = templateFactory;
setViewClass(MustacheView.class);
}

Expand All @@ -47,8 +47,4 @@ protected AbstractUrlBasedView buildView(String viewName) throws Exception {
return view;
}

@Required
public void setTemplateFactory(MustacheTemplateFactory templateFactory) {
this.templateFactory = templateFactory;
}
}
}
Loading