freemarker-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ddek...@apache.org
Subject [1/5] incubator-freemarker git commit: FREEMARKER-55: stringifying string/boolean/date model in url function. otherwise exception
Date Tue, 19 Sep 2017 06:03:54 GMT
Repository: incubator-freemarker
Updated Branches:
  refs/heads/3 12a2d49d0 -> f5a44238e


FREEMARKER-55: stringifying string/boolean/date model in url function. otherwise exception


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/4779234b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/4779234b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/4779234b

Branch: refs/heads/3
Commit: 4779234b67bb9c6ab0f0812d72ebe4b2152de04a
Parents: 14e4250
Author: Woonsan Ko <woonsan@apache.org>
Authored: Fri Sep 15 10:39:26 2017 -0400
Committer: Woonsan Ko <woonsan@apache.org>
Committed: Fri Sep 15 10:39:26 2017 -0400

----------------------------------------------------------------------
 .../AbstractSpringTemplateCallableModel.java    |  4 +-
 .../spring/model/MessageFunction.java           |  4 +-
 .../freemarker/spring/model/UrlFunction.java    | 23 ++++++---
 .../spring/example/mvc/users/User.java          |  6 +--
 .../example/mvc/users/UserController.java       |  4 +-
 .../example/mvc/users/UserRepository.java       | 16 +++----
 .../spring/model/BindDirectiveTest.java         |  2 +-
 .../spring/model/EvalFunctionTest.java          |  2 +-
 .../spring/model/MessageFunctionTest.java       |  4 +-
 .../spring/model/NestedPathDirectiveTest.java   |  2 +-
 .../spring/model/ThemeFunctionTest.java         |  2 +-
 .../spring/model/UrlFunctionTest.java           | 49 ++++++++++++++------
 .../test/model/url-function-basic-usages.ftl    | 29 ++++++++++++
 13 files changed, 104 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4779234b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/AbstractSpringTemplateCallableModel.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/AbstractSpringTemplateCallableModel.java
b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/AbstractSpringTemplateCallableModel.java
index 1c3d71b..d6157b0 100644
--- a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/AbstractSpringTemplateCallableModel.java
+++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/AbstractSpringTemplateCallableModel.java
@@ -81,7 +81,7 @@ abstract class AbstractSpringTemplateCallableModel implements TemplateCallableMo
         final ObjectWrapper objectWrapper = env.getObjectWrapper();
 
         if (!(objectWrapper instanceof ObjectWrapperAndUnwrapper)) {
-            CallableUtils.newGenericExecuteException(
+            throw CallableUtils.newGenericExecuteException(
                     "The ObjectWrapper of environment isn't an instance of ObjectWrapperAndUnwrapper.",
this,
                     calledAsFunction);
         }
@@ -101,7 +101,7 @@ abstract class AbstractSpringTemplateCallableModel implements TemplateCallableMo
         TemplateModel rcModel = env.getVariable(AbstractTemplateView.SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE);
 
         if (rcModel == null) {
-            CallableUtils.newGenericExecuteException(
+            throw CallableUtils.newGenericExecuteException(
                     AbstractTemplateView.SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE + " not found.",
this, false);
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4779234b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/MessageFunction.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/MessageFunction.java
b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/MessageFunction.java
index 3755849..c6ac520 100644
--- a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/MessageFunction.java
+++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/MessageFunction.java
@@ -103,7 +103,7 @@ class MessageFunction extends AbstractSpringTemplateFunctionModel {
         final MessageSource messageSource = getMessageSource(requestContext);
 
         if (messageSource == null) {
-            CallableUtils.newGenericExecuteException("MessageSource not found.", this);
+            throw CallableUtils.newGenericExecuteException("MessageSource not found.", this);
         }
 
         String message = null;
@@ -135,7 +135,7 @@ class MessageFunction extends AbstractSpringTemplateFunctionModel {
                 message = messageSource.getMessage(code, (msgArgumentList == null) ? null
: msgArgumentList.toArray(),
                         null, requestContext.getLocale());
             } else {
-                CallableUtils.newNullOrOmittedArgumentException(CODE_PARAM_IDX, this);
+                throw CallableUtils.newNullOrOmittedArgumentException(CODE_PARAM_IDX, this);
             }
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4779234b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/UrlFunction.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/UrlFunction.java
b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/UrlFunction.java
index e2986a9..7f180ec 100644
--- a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/UrlFunction.java
+++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/UrlFunction.java
@@ -36,9 +36,11 @@ import org.apache.freemarker.core.Environment;
 import org.apache.freemarker.core.TemplateException;
 import org.apache.freemarker.core.model.ArgumentArrayLayout;
 import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper;
+import org.apache.freemarker.core.model.TemplateBooleanModel;
 import org.apache.freemarker.core.model.TemplateHashModelEx2;
 import org.apache.freemarker.core.model.TemplateHashModelEx2.KeyValuePairIterator;
 import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.TemplateNumberModel;
 import org.apache.freemarker.core.model.TemplateStringModel;
 import org.apache.freemarker.core.util.CallableUtils;
 import org.apache.freemarker.core.util.StringToIndexMap;
@@ -127,20 +129,27 @@ class UrlFunction extends AbstractSpringTemplateFunctionModel {
                     paramName = ((TemplateStringModel) paramNameModel).getAsString();
 
                     if (paramName.isEmpty()) {
-                        CallableUtils.newArgumentValueException(PARAMS_PARAM_IDX,
+                        throw CallableUtils.newArgumentValueException(PARAMS_PARAM_IDX,
                                 "Parameter name must be a non-blank string.", this);
                     }
 
                     if (paramValueModel instanceof TemplateStringModel) {
                         paramValue = ((TemplateStringModel) paramValueModel).getAsString();
+                    } else if (paramValueModel instanceof TemplateNumberModel) {
+                        paramValue = ((TemplateNumberModel) paramValueModel).getAsNumber().toString();
+                    } else if (paramValueModel instanceof TemplateBooleanModel) {
+                        paramValue = Boolean.toString(((TemplateBooleanModel) paramValueModel).getAsBoolean());
                     } else {
-                        paramValue = env.formatToPlainText(paramValueModel);
+                        throw CallableUtils.newArgumentValueException(PARAMS_PARAM_IDX,
+                                "Format the parameter manually to properly coerce it to a
URL parameter value string. "
+                                        + "e.g, date?string.iso, date?long, list?join('_'),
etc.",
+                                this);
                     }
 
                     params.add(new _KeyValuePair<String, String>(paramName, paramValue));
                 } else {
-                    CallableUtils.newArgumentValueException(PARAMS_PARAM_IDX,
-                            "Parameter name must be string.", this);
+                    throw CallableUtils.newArgumentValueException(PARAMS_PARAM_IDX,
+                            "Parameter name must be a string.", this);
                 }
             }
         }
@@ -214,7 +223,7 @@ class UrlFunction extends AbstractSpringTemplateFunctionModel {
                 try {
                     uri = uri.replace(template, UriUtils.encodePath(paramValue, encoding));
                 } catch (UnsupportedEncodingException e) {
-                    CallableUtils.newGenericExecuteException("Cannot encode URI. " + e, this);
+                    throw CallableUtils.newGenericExecuteException("Cannot encode URI. "
+ e, this);
                 }
             } else {
                 template = URL_TEMPLATE_DELIMITER_PREFIX + '/' + paramName + URL_TEMPLATE_DELIMITER_SUFFIX;
@@ -225,7 +234,7 @@ class UrlFunction extends AbstractSpringTemplateFunctionModel {
                     try {
                         uri = uri.replace(template, UriUtils.encodePathSegment(paramValue,
encoding));
                     } catch (UnsupportedEncodingException e) {
-                        CallableUtils.newGenericExecuteException("Cannot encode URI. " +
e, this);
+                        throw CallableUtils.newGenericExecuteException("Cannot encode URI.
" + e, this);
                     }
                 }
             }
@@ -258,7 +267,7 @@ class UrlFunction extends AbstractSpringTemplateFunctionModel {
                         queryStringBuilder.append(UriUtils.encodeQueryParam(paramValue, encoding));
                     }
                 } catch (UnsupportedEncodingException e) {
-                    CallableUtils.newGenericExecuteException("Cannot encode query parameter.
" + e, this);
+                    throw CallableUtils.newGenericExecuteException("Cannot encode query parameter.
" + e, this);
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4779234b/freemarker-spring/src/test/java/org/apache/freemarker/spring/example/mvc/users/User.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/test/java/org/apache/freemarker/spring/example/mvc/users/User.java
b/freemarker-spring/src/test/java/org/apache/freemarker/spring/example/mvc/users/User.java
index 23d31dc..41b42c4 100644
--- a/freemarker-spring/src/test/java/org/apache/freemarker/spring/example/mvc/users/User.java
+++ b/freemarker-spring/src/test/java/org/apache/freemarker/spring/example/mvc/users/User.java
@@ -23,7 +23,7 @@ import java.util.Date;
 
 public class User {
 
-    private Integer id;
+    private Long id;
     private String password;
     private String email;
     private String firstName;
@@ -33,11 +33,11 @@ public class User {
     public User() {
     }
 
-    public User(final Integer id) {
+    public User(final Long id) {
         this.id = id;
     }
 
-    public Integer getId() {
+    public Long getId() {
         return id;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4779234b/freemarker-spring/src/test/java/org/apache/freemarker/spring/example/mvc/users/UserController.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/test/java/org/apache/freemarker/spring/example/mvc/users/UserController.java
b/freemarker-spring/src/test/java/org/apache/freemarker/spring/example/mvc/users/UserController.java
index 09a416d..5b1799e 100644
--- a/freemarker-spring/src/test/java/org/apache/freemarker/spring/example/mvc/users/UserController.java
+++ b/freemarker-spring/src/test/java/org/apache/freemarker/spring/example/mvc/users/UserController.java
@@ -60,7 +60,7 @@ public class UserController {
     public String listUsers(@RequestParam(value = "viewName", required = false) String viewName,
Model model) {
         List<User> users = new LinkedList<>();
 
-        for (Integer id : userRepository.getUserIds()) {
+        for (Long id : userRepository.getUserIds()) {
             users.add(userRepository.getUser(id));
         }
 
@@ -70,7 +70,7 @@ public class UserController {
     }
 
     @RequestMapping(value = "/users/{id:\\d+}", method = RequestMethod.GET)
-    public String getUser(@PathVariable("id") Integer id,
+    public String getUser(@PathVariable("id") Long id,
             @RequestParam(value = "viewName", required = false) String viewName, Model model)
{
         User user = userRepository.getUser(id);
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4779234b/freemarker-spring/src/test/java/org/apache/freemarker/spring/example/mvc/users/UserRepository.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/test/java/org/apache/freemarker/spring/example/mvc/users/UserRepository.java
b/freemarker-spring/src/test/java/org/apache/freemarker/spring/example/mvc/users/UserRepository.java
index 5049521..1f1a9e2 100644
--- a/freemarker-spring/src/test/java/org/apache/freemarker/spring/example/mvc/users/UserRepository.java
+++ b/freemarker-spring/src/test/java/org/apache/freemarker/spring/example/mvc/users/UserRepository.java
@@ -30,21 +30,21 @@ import org.springframework.stereotype.Repository;
 @Repository
 public class UserRepository {
 
-    private Map<Integer, User> usersMap = new ConcurrentHashMap<>();
+    private Map<Long, User> usersMap = new ConcurrentHashMap<>();
     {
-        Integer id = 101;
+        Long id = 101L;
         User user = new User(id);
         user.setEmail("john@example.com");
         user.setFirstName("John");
         user.setLastName("Doe");
         Calendar birthDate = Calendar.getInstance();
-        birthDate.set(Calendar.YEAR, 1971);
+        birthDate.set(Calendar.YEAR, 1973);
         birthDate.set(Calendar.MONTH, Calendar.JANUARY);
         birthDate.set(Calendar.DATE, 5);
         user.setBirthDate(birthDate.getTime());
         usersMap.put(id, user);
 
-        id = 102;
+        id = 102L;
         user = new User(id);
         user.setEmail("jane@example.com");
         user.setFirstName("Jane");
@@ -57,11 +57,11 @@ public class UserRepository {
         usersMap.put(id, user);
     }
 
-    public synchronized Set<Integer> getUserIds() {
+    public synchronized Set<Long> getUserIds() {
         return new TreeSet<>(usersMap.keySet());
     }
 
-    public synchronized User getUser(final Integer id) {
+    public synchronized User getUser(final Long id) {
         if (id == null) {
             throw new IllegalArgumentException("ID must be non-null.");
         }
@@ -76,7 +76,7 @@ public class UserRepository {
     }
 
     public synchronized User addOrUpdateUser(final User user) {
-        final Integer id = user.getId();
+        final Long id = user.getId();
         User newUser = cloneUser(user, id);
         usersMap.put(id, newUser);
         return cloneUser(newUser, id);
@@ -91,7 +91,7 @@ public class UserRepository {
         return user != null;
     }
 
-    private User cloneUser(final User source, final Integer id) {
+    private User cloneUser(final User source, final Long id) {
         User clone = new User(id);
         clone.setPassword(source.getPassword());
         clone.setEmail(source.getEmail());

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4779234b/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/BindDirectiveTest.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/BindDirectiveTest.java
b/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/BindDirectiveTest.java
index b2a6cd5..0b21a47 100644
--- a/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/BindDirectiveTest.java
+++ b/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/BindDirectiveTest.java
@@ -59,7 +59,7 @@ public class BindDirectiveTest {
 
     @Test
     public void testBasicUsages() throws Exception {
-        final Integer userId = userRepository.getUserIds().iterator().next();
+        final Long userId = userRepository.getUserIds().iterator().next();
         final User user = userRepository.getUser(userId);
         mockMvc.perform(get("/users/{userId}.", userId).param("viewName", "test/model/bind-directive-basic-usages")
                 .accept(MediaType.parseMediaType("text/html"))).andExpect(status().isOk())

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4779234b/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/EvalFunctionTest.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/EvalFunctionTest.java
b/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/EvalFunctionTest.java
index 45d98b2..1e92292 100644
--- a/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/EvalFunctionTest.java
+++ b/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/EvalFunctionTest.java
@@ -60,7 +60,7 @@ public class EvalFunctionTest {
 
     @Test
     public void testBasicUsages() throws Exception {
-        final Integer userId = userRepository.getUserIds().iterator().next();
+        final Long userId = userRepository.getUserIds().iterator().next();
         final User user = userRepository.getUser(userId);
         mockMvc.perform(get("/users/").param("viewName", "test/model/eval-function-basic-usages")
                 .accept(MediaType.parseMediaType("text/html"))).andExpect(status().isOk())

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4779234b/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/MessageFunctionTest.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/MessageFunctionTest.java
b/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/MessageFunctionTest.java
index d043bfe..37af7eb 100644
--- a/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/MessageFunctionTest.java
+++ b/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/MessageFunctionTest.java
@@ -59,7 +59,7 @@ public class MessageFunctionTest {
 
     @Test
     public void testBasicUsages() throws Exception {
-        final Integer userId = userRepository.getUserIds().iterator().next();
+        final Long userId = userRepository.getUserIds().iterator().next();
         final User user = userRepository.getUser(userId);
         mockMvc.perform(get("/users/{userId}/", userId).param("viewName", "test/model/message-function-basic-usages")
                 .accept(MediaType.parseMediaType("text/html"))).andExpect(status().isOk())
@@ -72,7 +72,7 @@ public class MessageFunctionTest {
 
     @Test
     public void testWithMessageSourceResolvable() throws Exception {
-        final Integer nonExistingUserId = 0;
+        final Long nonExistingUserId = 0L;
         mockMvc.perform(
                 get("/users/{userId}/", nonExistingUserId).param("viewName", "test/model/message-function-basic-usages")
                         .accept(MediaType.parseMediaType("text/html")))

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4779234b/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/NestedPathDirectiveTest.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/NestedPathDirectiveTest.java
b/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/NestedPathDirectiveTest.java
index a4999f5..f5f7d18 100644
--- a/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/NestedPathDirectiveTest.java
+++ b/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/NestedPathDirectiveTest.java
@@ -59,7 +59,7 @@ public class NestedPathDirectiveTest {
 
     @Test
     public void testBasicUsages() throws Exception {
-        final Integer userId = userRepository.getUserIds().iterator().next();
+        final Long userId = userRepository.getUserIds().iterator().next();
         final User user = userRepository.getUser(userId);
         mockMvc.perform(get("/users/{userId}.", userId).param("viewName", "test/model/nestedpath-directive-basic-usages")
                 .accept(MediaType.parseMediaType("text/html"))).andExpect(status().isOk())

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4779234b/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/ThemeFunctionTest.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/ThemeFunctionTest.java
b/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/ThemeFunctionTest.java
index 804b76d..5dd4bdc 100644
--- a/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/ThemeFunctionTest.java
+++ b/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/ThemeFunctionTest.java
@@ -65,7 +65,7 @@ public class ThemeFunctionTest {
     public void testBasicUsages() throws Exception {
         final MessageSource defaultThemeMessageSource = themeSource.getTheme("default").getMessageSource();
 
-        final Integer userId = userRepository.getUserIds().iterator().next();
+        final Long userId = userRepository.getUserIds().iterator().next();
         mockMvc.perform(get("/users/{userId}/", userId).param("viewName", "test/model/theme-function-basic-usages")
                 .accept(MediaType.parseMediaType("text/html"))).andExpect(status().isOk())
                 .andExpect(content().contentTypeCompatibleWith("text/html")).andDo(print())

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4779234b/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/UrlFunctionTest.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/UrlFunctionTest.java
b/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/UrlFunctionTest.java
index 8435bfc..3079556 100644
--- a/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/UrlFunctionTest.java
+++ b/freemarker-spring/src/test/java/org/apache/freemarker/spring/model/UrlFunctionTest.java
@@ -19,12 +19,10 @@
 
 package org.apache.freemarker.spring.model;
 
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.xpath;
+import java.text.DecimalFormat;
+import java.text.SimpleDateFormat;
 
+import org.apache.freemarker.spring.example.mvc.users.User;
 import org.apache.freemarker.spring.example.mvc.users.UserRepository;
 import org.junit.Before;
 import org.junit.Test;
@@ -38,11 +36,21 @@ import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 import org.springframework.web.context.WebApplicationContext;
 
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.xpath;
+
 @RunWith(SpringJUnit4ClassRunner.class)
 @WebAppConfiguration("classpath:META-INF/web-resources")
 @ContextConfiguration(locations = { "classpath:org/apache/freemarker/spring/example/mvc/users/users-mvc-context.xml"
})
 public class UrlFunctionTest {
 
+    private static final String TEMPLATE_NUMBER_FORMAT = "00000000";
+
+    private static final String TEMPLATE_DATE_FORMAT = "yyyy-MM-dd";
+
     @Autowired
     private WebApplicationContext wac;
 
@@ -58,19 +66,34 @@ public class UrlFunctionTest {
 
     @Test
     public void testBasicUsages() throws Exception {
-        final Integer userId = userRepository.getUserIds().iterator().next();
+        final Long userId = userRepository.getUserIds().iterator().next();
+        final String formattedUerId = new DecimalFormat(TEMPLATE_NUMBER_FORMAT).format(userId);
+        final User user = userRepository.getUser(userId);
         mockMvc.perform(get("/users/").param("viewName", "test/model/url-function-basic-usages")
                 .accept(MediaType.parseMediaType("text/html"))).andExpect(status().isOk())
                 .andExpect(content().contentTypeCompatibleWith("text/html")).andDo(print())
-                .andExpect(xpath("//h2[@id='usersListHeader']//a/@href", userId).string("/users/"))
-                .andExpect(xpath("//h3[@id='usersListHeaderWithSortParams']//a/@href", userId)
+                .andExpect(xpath("//h2[@id='usersListHeader']//a/@href").string("/users/"))
+                .andExpect(xpath("//h3[@id='usersListHeaderWithSortParams']//a/@href")
                         .string("/users/?sortField=birthDate&sortDirection=descending"))
-                .andExpect(xpath("//h2[@id='otherAppsUsersListHeader']//a/@href", userId).string("/otherapp/users/"))
-                .andExpect(xpath("//h3[@id='otherAppsUsersListHeaderWithSortParams']//a/@href",
userId)
+                .andExpect(xpath("//h2[@id='otherAppsUsersListHeader']//a/@href").string("/otherapp/users/"))
+                .andExpect(xpath("//h3[@id='otherAppsUsersListHeaderWithSortParams']//a/@href")
                         .string("/otherapp/users/?sortField=birthDate&sortDirection=descending"))
-                .andExpect(xpath("//div[@id='user-%s']//a[@class='userIdLink']/@href", userId).string("/users/"
+ userId + "/"))
-                .andExpect(xpath("//div[@id='user-%s']//a[@class='userNameLink']/@href",
userId).string("/users/" + userId + "/"))
-                .andExpect(xpath("//div[@id='freeMarkerManualUrl']//a/@href", userId)
+                .andExpect(xpath("//div[@id='user-%s']//a[@class='userIdLink']/@href", formattedUerId)
+                        .string("/users/" + userId + "/"))
+                .andExpect(xpath("//div[@id='user-%s']//a[@class='userNameLink']/@href",
formattedUerId)
+                        .string("/users/" + formattedUerId + "/"))
+                .andExpect(xpath("//div[@id='user-%s']//a[@class='badUserBirthDateLink']/@href",
formattedUerId)
+                        .doesNotExist())
+                .andExpect(xpath("//div[@id='user-%s']//a[@class='goodUserBirthDateLink']/@href",
formattedUerId)
+                        .string("/users/" + userId + "/?birthDate="
+                                + new SimpleDateFormat(TEMPLATE_DATE_FORMAT).format(user.getBirthDate())))
+                .andExpect(xpath("//div[@id='listLinkTest']//a[@class='badListLink']/@href").doesNotExist())
+                .andExpect(xpath("//div[@id='listLinkTest']//a[@class='goodListLink']/@href")
+                        .string("/users/?items=101_102"))
+                .andExpect(xpath("//div[@id='mapLinkTest']//a[@class='badMapLink']/@href").doesNotExist())
+                .andExpect(xpath("//div[@id='mapLinkTest']//a[@class='goodMapLink']/@href")
+                        .string("/users/?items=101_102"))
+                .andExpect(xpath("//div[@id='freeMarkerManualUrl']//a/@href")
                         .string("http://freemarker.org/docs/index.html"));
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4779234b/freemarker-spring/src/test/resources/META-INF/web-resources/views/test/model/url-function-basic-usages.ftl
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/test/resources/META-INF/web-resources/views/test/model/url-function-basic-usages.ftl
b/freemarker-spring/src/test/resources/META-INF/web-resources/views/test/model/url-function-basic-usages.ftl
index e25a2d5..8cc7c65 100644
--- a/freemarker-spring/src/test/resources/META-INF/web-resources/views/test/model/url-function-basic-usages.ftl
+++ b/freemarker-spring/src/test/resources/META-INF/web-resources/views/test/model/url-function-basic-usages.ftl
@@ -20,6 +20,9 @@
 <html>
 <body>
 
+<#-- NOTE: spring.url function should not use this number format. -->
+<#setting numberFormat="00000000" />
+
 <h2 id="usersListHeader">
   <a href="${spring.url('/users/')}">Users List</a>
 </h2>
@@ -42,6 +45,13 @@
       <div id="user-${user.id!}">
         <a class="userIdLink" href="${spring.url('/users/{userId}/', userId=user.id)}">${user.id!}</a>
         <a class="userNameLink" href="${spring.url('/users/${user.id}/')}">${user.firstName!}
${user.lastName!}</a>
+
+        <#attempt>
+          <a class="badUserBirthDateLink" href="${spring.url('/users/{userId}/', userId=user.id,
birthDate=user.birthDate)}">${user.birthDate?date}</a>
+        <#recover>
+          <a class="goodUserBirthDateLink" href="${spring.url('/users/{userId}/', userId=user.id,
birthDate=user.birthDate?string['yyyy-MM-dd'])}">${user.birthDate?date}</a>
+        </#attempt>
+
       </div>
     </li>
   </#list>
@@ -51,5 +61,24 @@
   <a href="${spring.url('http://freemarker.org/docs/index.html')}">Apache FreeMarker
Manual</a>
 </div>
 
+<#-- List or Map is not allowed to pass as url parameter directly. -->
+<#assign userIdList = [ '101', '102' ] />
+<#assign userInfoMap = { "101": "John", "102": "Jane" } />
+
+<div id="listLinkTest">
+  <#attempt>
+    <a class="badListLink" href="${spring.url('/users/', items=userIdList)}">User List
Link</a>
+  <#recover>
+    <a class="goodListLink" href="${spring.url('/users/', items=userIdList?join('_'))}">User
List Link</a>
+  </#attempt>
+</div>
+<div id="mapLinkTest">
+  <#attempt>
+    <a class="badMapLink" href="${spring.url('/users/', items=userInfoMap)}">User List
Link</a>
+  <#recover>
+    <a class="goodMapLink" href="${spring.url('/users/', items=userInfoMap?keys?join('_'))}">User
List Link</a>
+  </#attempt>
+</div>
+
 </body>
 </html>


Mime
View raw message