diff --git a/core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java b/core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java
index 400674d2de..f932373678 100644
--- a/core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java
+++ b/core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java
@@ -56,6 +56,9 @@
import com.opensymphony.xwork2.conversion.impl.DefaultConversionAnnotationProcessor;
import com.opensymphony.xwork2.conversion.impl.DefaultConversionFileProcessor;
import com.opensymphony.xwork2.security.NotExcludedAcceptedPatternsChecker;
+import org.apache.struts2.components.date.DateFormatter;
+import org.apache.struts2.components.date.DateTimeFormatterAdapter;
+import org.apache.struts2.components.date.SimpleDateFormatAdapter;
import org.apache.struts2.conversion.StrutsConversionPropertiesProcessor;
import com.opensymphony.xwork2.conversion.impl.DefaultObjectTypeDeterminer;
import org.apache.struts2.conversion.StrutsTypeConverterCreator;
@@ -218,6 +221,9 @@ public void register(ContainerBuilder builder, LocatableProperties props)
, Scope.SINGLETON)
.factory(ValueSubstitutor.class, EnvsValueSubstitutor.class, Scope.SINGLETON)
+
+ .factory(DateFormatter.class, "simpleDateFormatter", SimpleDateFormatAdapter.class, Scope.SINGLETON)
+ .factory(DateFormatter.class, "dateTimeFormatter", DateTimeFormatterAdapter.class, Scope.SINGLETON)
;
props.setProperty(StrutsConstants.STRUTS_ENABLE_DYNAMIC_METHOD_INVOCATION, Boolean.FALSE.toString());
diff --git a/core/src/main/java/org/apache/struts2/StrutsConstants.java b/core/src/main/java/org/apache/struts2/StrutsConstants.java
index 789b7c3886..64ac93b047 100644
--- a/core/src/main/java/org/apache/struts2/StrutsConstants.java
+++ b/core/src/main/java/org/apache/struts2/StrutsConstants.java
@@ -18,6 +18,7 @@
*/
package org.apache.struts2;
+import org.apache.struts2.components.date.DateFormatter;
import org.apache.struts2.dispatcher.mapper.CompositeActionMapper;
/**
@@ -384,4 +385,6 @@ public final class StrutsConstants {
public static final String STRUTS_CHAINING_COPY_MESSAGES = "struts.chaining.copyMessages";
public static final String STRUTS_OBJECT_FACTORY_CLASSLOADER = "struts.objectFactory.classloader";
+ /** See {@link org.apache.struts2.components.Date#setDateFormatter(DateFormatter)} */
+ public static final String STRUTS_DATE_FORMATTER = "struts.date.formatter";
}
diff --git a/core/src/main/java/org/apache/struts2/components/Date.java b/core/src/main/java/org/apache/struts2/components/Date.java
index 5f65d9c7b9..ad174fd111 100644
--- a/core/src/main/java/org/apache/struts2/components/Date.java
+++ b/core/src/main/java/org/apache/struts2/components/Date.java
@@ -18,29 +18,29 @@
*/
package org.apache.struts2.components;
-import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.TextProvider;
+import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.ValueStack;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.apache.struts2.components.date.DateFormatter;
import org.apache.struts2.views.annotations.StrutsTag;
import org.apache.struts2.views.annotations.StrutsTagAttribute;
import java.io.IOException;
import java.io.Writer;
import java.time.Instant;
+import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
-import java.time.format.DateTimeFormatter;
-import java.time.format.FormatStyle;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
/**
*
- *
+ *
* Format Date object in different ways.
*
* The date tag will allow you to format a Date in a quick and easy way.
@@ -59,6 +59,12 @@
*
*
*
+ * Note: Since Struts 2.6 a new Java 8 API has been used to format the Date, it's based on
+ * DateTimeFormatter
+ * which uses a bit different patterns.
+ *
+ *
+ *
* Configurable attributes are:
*
*
@@ -130,8 +136,8 @@
* if one is not found DateFormat.MEDIUM format will be used |
*
*
- *
- *
+ *
+ *
*
*
*
Examples
@@ -145,12 +151,12 @@
*
*
* Date
- *
*/
-@StrutsTag(name="date", tldBodyContent="empty", tldTagClass="org.apache.struts2.views.jsp.DateTag", description="Render a formatted date.")
+@StrutsTag(name = "date", tldBodyContent = "empty", tldTagClass = "org.apache.struts2.views.jsp.DateTag", description = "Render a formatted date.")
public class Date extends ContextBean {
private static final Logger LOG = LogManager.getLogger(Date.class);
+
/**
* Property name to fall back when no format is specified
*/
@@ -202,17 +208,18 @@ public class Date extends ContextBean {
private String timezone;
+ private DateFormatter dateFormatter;
+
public Date(ValueStack stack) {
super(stack);
}
- private TextProvider findProviderInStack() {
- for (Object o : getStack().getRoot()) {
- if (o instanceof TextProvider) {
- return (TextProvider) o;
- }
- }
- return null;
+ /**
+ * An instance of {@link DateFormatter}
+ */
+ @Inject
+ public void setDateFormatter(DateFormatter dateFormatter) {
+ this.dateFormatter = dateFormatter;
}
/**
@@ -280,6 +287,8 @@ public String formatTime(TextProvider tp, ZonedDateTime date) {
@Override
public boolean end(Writer writer, String body) {
+ TextProvider textProvider = findProviderInStack();
+
ZonedDateTime date = null;
final ZoneId tz = getTimeZone();
// find the name on the valueStack
@@ -292,26 +301,27 @@ public boolean end(Writer writer, String body) {
date = Instant.ofEpochMilli((long) dateObject).atZone(tz);
} else if (dateObject instanceof LocalDateTime) {
date = ((LocalDateTime) dateObject).atZone(tz);
+ } else if (dateObject instanceof LocalDate) {
+ date = ((LocalDate) dateObject).atStartOfDay(tz);
} else if (dateObject instanceof Instant) {
date = ((Instant) dateObject).atZone(tz);
} else {
if (devMode) {
- TextProvider tp = findProviderInStack();
String developerNotification = "";
- if (tp != null) {
- developerNotification = findProviderInStack().getText(
- "devmode.notification",
- "Developer Notification:\n{0}",
- new String[]{
- "Expression [" + name + "] passed to tag which was evaluated to [" + dateObject + "]("
- + (dateObject != null ? dateObject.getClass() : "null") + ") isn't supported!"
- }
+ if (textProvider != null) {
+ developerNotification = textProvider.getText(
+ "devmode.notification",
+ "Developer Notification:\n{0}",
+ new String[]{
+ "Expression [" + name + "] passed to tag which was evaluated to [" + dateObject + "]("
+ + (dateObject != null ? dateObject.getClass() : "null") + ") isn't supported!"
+ }
);
}
LOG.warn(developerNotification);
} else {
LOG.debug("Expression [{}] passed to tag which was evaluated to [{}]({}) isn't supported!",
- name, dateObject, (dateObject != null ? dateObject.getClass() : "null"));
+ name, dateObject, (dateObject != null ? dateObject.getClass() : "null"));
}
}
@@ -321,33 +331,11 @@ public boolean end(Writer writer, String body) {
}
String msg;
if (date != null) {
- TextProvider tp = findProviderInStack();
- if (tp != null) {
+ if (textProvider != null) {
if (nice) {
- msg = formatTime(tp, date);
+ msg = formatTime(textProvider, date);
} else {
- DateTimeFormatter dtf;
- if (format == null) {
- String globalFormat = null;
-
- // if the format is not specified, fall back using the
- // defined property DATETAG_PROPERTY
- globalFormat = tp.getText(DATETAG_PROPERTY);
-
- // if tp.getText can not find the property then the
- // returned string is the same as input =
- // DATETAG_PROPERTY
- if (globalFormat != null
- && !DATETAG_PROPERTY.equals(globalFormat)) {
- dtf = DateTimeFormatter.ofPattern(globalFormat, ActionContext.getContext().getLocale());
- } else {
- dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
- .withLocale(ActionContext.getContext().getLocale());
- }
- } else {
- dtf = DateTimeFormatter.ofPattern(format, ActionContext.getContext().getLocale());
- }
- msg = dtf.format(date);
+ msg = formatDate(textProvider, date);
}
if (msg != null) {
try {
@@ -365,6 +353,20 @@ public boolean end(Writer writer, String body) {
return super.end(writer, "");
}
+ private String formatDate(TextProvider textProvider, ZonedDateTime date) {
+ String useFormat = format;
+ if (useFormat == null) {
+ // if the format is not specified, fall back using the defined property DATETAG_PROPERTY
+ useFormat = textProvider.getText(DATETAG_PROPERTY);
+ if (DATETAG_PROPERTY.equals(useFormat)) {
+ // if tp.getText can not find the property then the
+ // returned string is the same as input = DATETAG_PROPERTY
+ useFormat = null;
+ }
+ }
+ return dateFormatter.format(date, useFormat);
+ }
+
private ZoneId getTimeZone() {
ZoneId tz = ZoneId.systemDefault();
if (timezone != null) {
@@ -378,17 +380,26 @@ private ZoneId getTimeZone() {
return tz;
}
- @StrutsTagAttribute(description="Date or DateTime format pattern", rtexprvalue=false)
+ private TextProvider findProviderInStack() {
+ for (Object o : getStack().getRoot()) {
+ if (o instanceof TextProvider) {
+ return (TextProvider) o;
+ }
+ }
+ return null;
+ }
+
+ @StrutsTagAttribute(description = "Date or DateTime format pattern")
public void setFormat(String format) {
this.format = format;
}
- @StrutsTagAttribute(description="Whether to print out the date nicely", type="Boolean", defaultValue="false")
+ @StrutsTagAttribute(description = "Whether to print out the date nicely", type = "Boolean", defaultValue = "false")
public void setNice(boolean nice) {
this.nice = nice;
}
- @StrutsTagAttribute(description = "The specific timezone in which to format the date", required = false)
+ @StrutsTagAttribute(description = "The specific timezone in which to format the date")
public void setTimezone(String timezone) {
this.timezone = timezone;
}
@@ -400,7 +411,7 @@ public String getName() {
return name;
}
- @StrutsTagAttribute(description="The date value to format", required=true)
+ @StrutsTagAttribute(description = "The date value to format", required = true)
public void setName(String name) {
this.name = name;
}
diff --git a/core/src/main/java/org/apache/struts2/components/date/DateFormatter.java b/core/src/main/java/org/apache/struts2/components/date/DateFormatter.java
new file mode 100644
index 0000000000..282daaa061
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/components/date/DateFormatter.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.struts2.components.date;
+
+import java.time.temporal.TemporalAccessor;
+
+/**
+ * Allows defines a wrapper around different formatting APIs, like old SimpleDateFormat
+ * and new DateTimeFormatter introduced in Java 8 Date/Time API
+ *
+ * New instance will be injected using {@link org.apache.struts2.StrutsConstants#STRUTS_DATE_FORMATTER}
+ */
+public interface DateFormatter {
+
+ /**
+ * Formats provided temporal with the given format
+ *
+ * @param temporal Java 8 {@link TemporalAccessor}
+ * @param format implementation specific format
+ * @return a string representation of the formatted `temporal`
+ */
+ String format(TemporalAccessor temporal, String format);
+
+}
diff --git a/core/src/main/java/org/apache/struts2/components/date/DateTimeFormatterAdapter.java b/core/src/main/java/org/apache/struts2/components/date/DateTimeFormatterAdapter.java
new file mode 100644
index 0000000000..05767ab1b3
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/components/date/DateTimeFormatterAdapter.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.struts2.components.date;
+
+import com.opensymphony.xwork2.ActionContext;
+
+import java.time.format.DateTimeFormatter;
+import java.time.format.FormatStyle;
+import java.time.temporal.TemporalAccessor;
+import java.util.Locale;
+
+public class DateTimeFormatterAdapter implements DateFormatter {
+
+ @Override
+ public String format(TemporalAccessor temporal, String format) {
+ DateTimeFormatter dtf;
+ Locale locale = ActionContext.getContext().getLocale();
+ if (format == null) {
+ dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
+ .withLocale(locale);
+ } else {
+ dtf = DateTimeFormatter.ofPattern(format, locale);
+ }
+ return dtf.format(temporal);
+ }
+
+}
diff --git a/core/src/main/java/org/apache/struts2/components/date/SimpleDateFormatAdapter.java b/core/src/main/java/org/apache/struts2/components/date/SimpleDateFormatAdapter.java
new file mode 100644
index 0000000000..38f3c52969
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/components/date/SimpleDateFormatAdapter.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.struts2.components.date;
+
+import com.opensymphony.xwork2.ActionContext;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.temporal.TemporalAccessor;
+import java.util.Date;
+import java.util.Locale;
+
+public class SimpleDateFormatAdapter implements DateFormatter {
+
+ @Override
+ public String format(TemporalAccessor temporal, String format) {
+ DateFormat df;
+ Locale locale = ActionContext.getContext().getLocale();
+ if (format == null) {
+ df = SimpleDateFormat.getDateInstance(DateFormat.MEDIUM, locale);
+ } else {
+ df = new SimpleDateFormat(format, locale);
+ }
+ return df.format(new Date(Instant.from(temporal).toEpochMilli()));
+ }
+
+}
diff --git a/core/src/main/java/org/apache/struts2/config/StrutsBeanSelectionProvider.java b/core/src/main/java/org/apache/struts2/config/StrutsBeanSelectionProvider.java
index ade6aa0b07..69aa9258ed 100644
--- a/core/src/main/java/org/apache/struts2/config/StrutsBeanSelectionProvider.java
+++ b/core/src/main/java/org/apache/struts2/config/StrutsBeanSelectionProvider.java
@@ -54,13 +54,12 @@
import com.opensymphony.xwork2.util.TextParser;
import com.opensymphony.xwork2.util.ValueStackFactory;
import com.opensymphony.xwork2.util.location.LocatableProperties;
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.LogManager;
import com.opensymphony.xwork2.util.reflection.ReflectionContextFactory;
import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
import com.opensymphony.xwork2.validator.ActionValidatorManager;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.components.UrlRenderer;
+import org.apache.struts2.components.date.DateFormatter;
import org.apache.struts2.dispatcher.DispatcherErrorHandler;
import org.apache.struts2.dispatcher.StaticContentLoader;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
@@ -422,6 +421,8 @@ public void register(ContainerBuilder builder, LocatableProperties props) {
alias(NotExcludedAcceptedPatternsChecker.class, StrutsConstants.STRUTS_NOT_EXCLUDED_ACCEPTED_PATTERNS_CHECKER
, builder, props, Scope.SINGLETON);
+ alias(DateFormatter.class, StrutsConstants.STRUTS_DATE_FORMATTER, builder, props, Scope.SINGLETON);
+
switchDevMode(props);
}
diff --git a/core/src/main/resources/org/apache/struts2/default.properties b/core/src/main/resources/org/apache/struts2/default.properties
index 571dcf59e6..4456d10af5 100644
--- a/core/src/main/resources/org/apache/struts2/default.properties
+++ b/core/src/main/resources/org/apache/struts2/default.properties
@@ -243,4 +243,10 @@ struts.handle.exception=true
### NOTE: The sample line below is *INTENTIONALLY* commented out, as this feature is disabled by default.
# struts.ognl.expressionMaxLength=256
+### Defines which named instance of DateFormatter to use, there are two instances:
+### - simpleDateFormatter (based on SimpleDateFormat)
+### - dateTimeFormatter (based on Java 8 Date/Time API)
+### These formatters are using a slightly different patterns, please check JavaDocs of both and more details is in WW-5016
+struts.date.formatter=dateTimeFormatter
+
### END SNIPPET: complete_file
diff --git a/core/src/main/resources/struts-default.xml b/core/src/main/resources/struts-default.xml
index 9dd8fbfa30..96b17b413c 100644
--- a/core/src/main/resources/struts-default.xml
+++ b/core/src/main/resources/struts-default.xml
@@ -216,7 +216,7 @@
-
+
@@ -228,6 +228,9 @@
+
+
+
diff --git a/core/src/test/java/org/apache/struts2/components/DateTest.java b/core/src/test/java/org/apache/struts2/components/DateTest.java
new file mode 100644
index 0000000000..2b9ca8bd71
--- /dev/null
+++ b/core/src/test/java/org/apache/struts2/components/DateTest.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.struts2.components;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.ValueStackFactory;
+import org.apache.struts2.StrutsInternalTestCase;
+import org.apache.struts2.components.date.SimpleDateFormatAdapter;
+
+import java.io.StringWriter;
+import java.io.Writer;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Map;
+
+public class DateTest extends StrutsInternalTestCase {
+
+ private Map context;
+ private ValueStack stack;
+
+ public void testSupportSimpleDateTimeFormat() {
+ // given
+ Date date = new Date(stack);
+ date.setDateFormatter(new SimpleDateFormatAdapter());
+
+ String format = "EEEE MMMM dd, hh:mm aa";
+ java.util.Date now = new java.util.Date();
+
+ String expected = new SimpleDateFormat(format, ActionContext.getContext().getLocale()).format(now);
+ context.put("myDate", now);
+
+ Writer writer = new StringWriter();
+
+ // when
+ date.setFormat(format);
+ date.setName("myDate");
+ date.setNice(false);
+ date.start(writer);
+ date.end(writer, "");
+
+ // then
+ assertEquals(expected, writer.toString());
+ }
+
+ public void testDefaultFormat() {
+ // given
+ Date date = new Date(stack);
+ date.setDateFormatter(new SimpleDateFormatAdapter());
+
+ java.util.Date now = new java.util.Date();
+
+ String expected = SimpleDateFormat.getDateInstance(DateFormat.MEDIUM, ActionContext.getContext().getLocale()).format(now);
+ context.put("myDate", now);
+
+ Writer writer = new StringWriter();
+
+ // when
+ date.setName("myDate");
+ date.setNice(false);
+ date.start(writer);
+ date.end(writer, "");
+
+ // then
+ assertEquals(expected, writer.toString());
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ stack = container.getInstance(ValueStackFactory.class).createValueStack();
+ context = stack.getContext();
+ }
+}
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/DateTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/DateTagTest.java
index 6f6e31eccc..05e267e05c 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/DateTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/DateTagTest.java
@@ -19,35 +19,33 @@
package org.apache.struts2.views.jsp.ui;
import com.opensymphony.xwork2.ActionContext;
-
import org.apache.struts2.TestAction;
+import org.apache.struts2.components.Component;
+import org.apache.struts2.components.DateTextField;
import org.apache.struts2.views.jsp.AbstractTagTest;
import org.apache.struts2.views.jsp.DateTag;
+import javax.servlet.jsp.JspException;
import java.text.DateFormat;
-import java.text.SimpleDateFormat;
import java.time.Instant;
+import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
-import java.util.TimeZone;
-import org.apache.struts2.components.Component;
-import org.apache.struts2.components.DateTextField;
/**
* Unit test for {@link org.apache.struts2.components.Date}.
- *
*/
public class DateTagTest extends AbstractTagTest {
private DateTag tag;
- public void testCustomFormat() throws Exception {
+ public void testCustomFormatForDateTime() throws Exception {
String format = "yyyy/MM/dd hh:mm:ss";
- Date now = new Date();
- String formatted = new SimpleDateFormat(format).format(now);
+ LocalDateTime now = LocalDateTime.now();
+ String formatted = DateTimeFormatter.ofPattern(format).format(now);
context.put("myDate", now);
tag.setName("myDate");
@@ -62,13 +60,55 @@ public void testCustomFormat() throws Exception {
freshTag.setPageContext(pageContext);
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ }
+
+ public void testCustomFormatForLong() throws Exception {
+ String format = "yyyy/MM/dd";
+ long now = new Date().getTime();
+ String formatted = DateTimeFormatter.ofPattern(format).format(Instant.ofEpochMilli(now).atZone(ZoneId.systemDefault()));
+ context.put("myDate", now);
+
+ tag.setName("myDate");
+ tag.setNice(false);
+ tag.setFormat(format);
+ tag.doStartTag();
+ tag.doEndTag();
+ assertEquals(formatted, writer.toString());
+
+ // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag().
+ DateTag freshTag = new DateTag();
+ freshTag.setPageContext(pageContext);
+ assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
+ "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ }
+
+ public void testCustomFormatForDate() throws Exception {
+ String format = "yyyy/MM/dd";
+ LocalDate now = LocalDate.now();
+ String formatted = DateTimeFormatter.ofPattern(format).format(now);
+ context.put("myDate", now);
+
+ tag.setName("myDate");
+ tag.setNice(false);
+ tag.setFormat(format);
+ tag.doStartTag();
+ tag.doEndTag();
+ assertEquals(formatted, writer.toString());
+
+ // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag().
+ DateTag freshTag = new DateTag();
+ freshTag.setPageContext(pageContext);
+ assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
+ "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testCustomFormat_clearTagStateSet() throws Exception {
String format = "yyyy/MM/dd hh:mm:ss";
- Date now = new Date();
- String formatted = new SimpleDateFormat(format).format(now);
+ LocalDateTime now = LocalDateTime.now();
+ String formatted = DateTimeFormatter.ofPattern(format).format(now);
context.put("myDate", now);
tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing.
@@ -86,13 +126,13 @@ public void testCustomFormat_clearTagStateSet() throws Exception {
freshTag.setPageContext(pageContext);
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testCustomGlobalFormatFormat() throws Exception {
String format = "yyyy/MM/dd hh:mm:ss";
- Date now = new Date();
- String formatted = new SimpleDateFormat(format).format(now);
+ LocalDateTime now = LocalDateTime.now();
+ String formatted = DateTimeFormatter.ofPattern(format).format(now);
context.put("myDate", now);
((TestAction) action).setText(org.apache.struts2.components.Date.DATETAG_PROPERTY, format);
@@ -106,10 +146,8 @@ public void testCustomGlobalFormatFormat() throws Exception {
public void testCustomFormatWithTimezone() throws Exception {
String format = "yyyy/MM/dd hh:mm:ss";
- Date now = Calendar.getInstance(TimeZone.getTimeZone("GMT+1")).getTime();
- SimpleDateFormat sdf = new SimpleDateFormat(format);
- sdf.setTimeZone(TimeZone.getTimeZone("GMT+1"));
- String formatted = sdf.format(now);
+ LocalDateTime now = LocalDateTime.now(ZoneId.of("GMT+1"));
+ String formatted = DateTimeFormatter.ofPattern(format).format(now);
context.put("myDate", now);
tag.setName("myDate");
@@ -126,15 +164,13 @@ public void testCustomFormatWithTimezone() throws Exception {
freshTag.setPageContext(pageContext);
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testCustomFormatWithTimezone_clearTagStateSet() throws Exception {
String format = "yyyy/MM/dd hh:mm:ss";
- Date now = Calendar.getInstance(TimeZone.getTimeZone("GMT+1")).getTime();
- SimpleDateFormat sdf = new SimpleDateFormat(format);
- sdf.setTimeZone(TimeZone.getTimeZone("GMT+1"));
- String formatted = sdf.format(now);
+ LocalDateTime now = LocalDateTime.now(ZoneId.of("GMT+1"));
+ String formatted = DateTimeFormatter.ofPattern(format).format(now);
context.put("myDate", now);
tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing.
@@ -153,15 +189,13 @@ public void testCustomFormatWithTimezone_clearTagStateSet() throws Exception {
freshTag.setPageContext(pageContext);
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testCustomFormatWithTimezoneAsExpression() throws Exception {
String format = "yyyy/MM/dd hh:mm:ss";
- Date now = Calendar.getInstance(TimeZone.getTimeZone("GMT+2")).getTime();
- SimpleDateFormat sdf = new SimpleDateFormat(format);
- sdf.setTimeZone(TimeZone.getTimeZone("GMT+2"));
- String formatted = sdf.format(now);
+ LocalDateTime now = LocalDateTime.now(ZoneId.of("GMT+2"));
+ String formatted = DateTimeFormatter.ofPattern(format).format(now);
context.put("myDate", now);
context.put("myTimezone", "GMT+2");
@@ -178,15 +212,13 @@ public void testCustomFormatWithTimezoneAsExpression() throws Exception {
freshTag.setPageContext(pageContext);
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testCustomFormatWithTimezoneAsExpression_clearTagStateSet() throws Exception {
String format = "yyyy/MM/dd hh:mm:ss";
- Date now = Calendar.getInstance(TimeZone.getTimeZone("GMT+2")).getTime();
- SimpleDateFormat sdf = new SimpleDateFormat(format);
- sdf.setTimeZone(TimeZone.getTimeZone("GMT+2"));
- String formatted = sdf.format(now);
+ LocalDateTime now = LocalDateTime.now(ZoneId.of("GMT+2"));
+ String formatted = DateTimeFormatter.ofPattern(format).format(now);
context.put("myDate", now);
context.put("myTimezone", "GMT+2");
@@ -206,13 +238,13 @@ public void testCustomFormatWithTimezoneAsExpression_clearTagStateSet() throws E
freshTag.setPageContext(pageContext);
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testCustomFormatCalendar() throws Exception {
String format = "yyyy/MM/dd hh:mm:ss";
Calendar calendar = Calendar.getInstance();
- String formatted = new SimpleDateFormat(format).format(calendar.getTime());
+ String formatted = DateTimeFormatter.ofPattern(format).format(calendar.toInstant().atZone(ZoneId.systemDefault()));
context.put("myDate", calendar);
tag.setName("myDate");
@@ -227,13 +259,13 @@ public void testCustomFormatCalendar() throws Exception {
freshTag.setPageContext(pageContext);
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testCustomFormatCalendar_clearTagStateSet() throws Exception {
String format = "yyyy/MM/dd hh:mm:ss";
Calendar calendar = Calendar.getInstance();
- String formatted = new SimpleDateFormat(format).format(calendar.getTime());
+ String formatted = DateTimeFormatter.ofPattern(format).format(calendar.toInstant().atZone(ZoneId.systemDefault()));
context.put("myDate", calendar);
tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing.
@@ -251,13 +283,13 @@ public void testCustomFormatCalendar_clearTagStateSet() throws Exception {
freshTag.setPageContext(pageContext);
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testCustomFormatLong() throws Exception {
String format = "yyyy/MM/dd hh:mm:ss";
Date date = new Date();
- String formatted = new SimpleDateFormat(format).format(date);
+ String formatted = DateTimeFormatter.ofPattern(format).format(date.toInstant().atZone(ZoneId.systemDefault()));
// long
context.put("myDate", date.getTime());
@@ -273,13 +305,13 @@ public void testCustomFormatLong() throws Exception {
freshTag.setPageContext(pageContext);
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testCustomFormatLong_clearTagStateSet() throws Exception {
String format = "yyyy/MM/dd hh:mm:ss";
Date date = new Date();
- String formatted = new SimpleDateFormat(format).format(date);
+ String formatted = DateTimeFormatter.ofPattern(format).format(date.toInstant().atZone(ZoneId.systemDefault()));
// long
context.put("myDate", date.getTime());
@@ -298,7 +330,7 @@ public void testCustomFormatLong_clearTagStateSet() throws Exception {
freshTag.setPageContext(pageContext);
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testCustomFormatLocalDateTime() throws Exception {
@@ -332,7 +364,7 @@ public void testCustomFormatInstant() throws Exception {
public void testDefaultFormat() throws Exception {
Date now = new Date();
String formatted = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM,
- ActionContext.getContext().getLocale()).format(now);
+ ActionContext.getContext().getLocale()).format(now);
context.put("myDate", now);
tag.setName("myDate");
@@ -346,13 +378,13 @@ public void testDefaultFormat() throws Exception {
freshTag.setPageContext(pageContext);
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testDefaultFormat_clearTagStateSet() throws Exception {
Date now = new Date();
String formatted = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM,
- ActionContext.getContext().getLocale()).format(now);
+ ActionContext.getContext().getLocale()).format(now);
context.put("myDate", now);
tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing.
@@ -369,13 +401,13 @@ public void testDefaultFormat_clearTagStateSet() throws Exception {
freshTag.setPageContext(pageContext);
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testCustomFormatAndComponent() throws Exception {
String format = "yyyy/MM/dd hh:mm:ss";
- Date now = new Date();
- String formatted = new SimpleDateFormat(format).format(now);
+ LocalDateTime now = LocalDateTime.now();
+ String formatted = DateTimeFormatter.ofPattern(format).format(now);
context.put("myDate", now);
tag.setName("myDate");
@@ -388,7 +420,7 @@ public void testCustomFormatAndComponent() throws Exception {
org.apache.struts2.components.Date component = (org.apache.struts2.components.Date) tag.getComponent();
assertEquals("myDate", component.getName());
assertEquals(format, component.getFormat());
- assertEquals(false, component.isNice());
+ assertFalse(component.isNice());
tag.doEndTag();
@@ -399,13 +431,13 @@ public void testCustomFormatAndComponent() throws Exception {
freshTag.setPageContext(pageContext);
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testCustomFormatAndComponent_clearTagStateSet() throws Exception {
String format = "yyyy/MM/dd hh:mm:ss";
- Date now = new Date();
- String formatted = new SimpleDateFormat(format).format(now);
+ LocalDateTime now = LocalDateTime.now();
+ String formatted = DateTimeFormatter.ofPattern(format).format(now);
context.put("myDate", now);
tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing.
@@ -420,7 +452,7 @@ public void testCustomFormatAndComponent_clearTagStateSet() throws Exception {
org.apache.struts2.components.Date component = (org.apache.struts2.components.Date) tag.getComponent();
assertEquals("myDate", component.getName());
assertEquals(format, component.getFormat());
- assertEquals(false, component.isNice());
+ assertFalse(component.isNice());
tag.doEndTag();
@@ -432,13 +464,13 @@ public void testCustomFormatAndComponent_clearTagStateSet() throws Exception {
freshTag.setPageContext(pageContext);
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testSetId() throws Exception {
String format = "yyyy/MM/dd hh:mm:ss";
- Date now = new Date();
- String formatted = new SimpleDateFormat(format).format(now);
+ LocalDateTime now = LocalDateTime.now();
+ String formatted = DateTimeFormatter.ofPattern(format).format(now);
context.put("myDate", now);
tag.setName("myDate");
@@ -454,13 +486,13 @@ public void testSetId() throws Exception {
freshTag.setPageContext(pageContext);
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testSetId_clearTagStateSet() throws Exception {
String format = "yyyy/MM/dd hh:mm:ss";
- Date now = new Date();
- String formatted = new SimpleDateFormat(format).format(now);
+ LocalDateTime now = LocalDateTime.now();
+ String formatted = DateTimeFormatter.ofPattern(format).format(now);
context.put("myDate", now);
tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing.
@@ -479,7 +511,7 @@ public void testSetId_clearTagStateSet() throws Exception {
freshTag.setPageContext(pageContext);
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testFutureNiceHour() throws Exception {
@@ -501,7 +533,7 @@ public void testFutureNiceHour() throws Exception {
freshTag.setPageContext(pageContext);
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testFutureNiceHour_clearTagStateSet() throws Exception {
@@ -526,7 +558,7 @@ public void testFutureNiceHour_clearTagStateSet() throws Exception {
freshTag.setPageContext(pageContext);
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testPastNiceHour() throws Exception {
@@ -548,7 +580,7 @@ public void testPastNiceHour() throws Exception {
freshTag.setPageContext(pageContext);
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testPastNiceHour_clearTagStateSet() throws Exception {
@@ -573,7 +605,7 @@ public void testPastNiceHour_clearTagStateSet() throws Exception {
freshTag.setPageContext(pageContext);
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testFutureNiceHourMinSec() throws Exception {
@@ -596,7 +628,7 @@ public void testFutureNiceHourMinSec() throws Exception {
freshTag.setPageContext(pageContext);
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testFutureNiceHourMinSec_clearTagStateSet() throws Exception {
@@ -622,7 +654,7 @@ public void testFutureNiceHourMinSec_clearTagStateSet() throws Exception {
freshTag.setPageContext(pageContext);
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testPastNiceHourMin() throws Exception {
@@ -645,7 +677,7 @@ public void testPastNiceHourMin() throws Exception {
freshTag.setPageContext(pageContext);
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testPastNiceHourMin_clearTagStateSet() throws Exception {
@@ -671,7 +703,7 @@ public void testPastNiceHourMin_clearTagStateSet() throws Exception {
freshTag.setPageContext(pageContext);
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testFutureLessOneMin() throws Exception {
@@ -693,7 +725,7 @@ public void testFutureLessOneMin() throws Exception {
freshTag.setPageContext(pageContext);
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testFutureLessOneMin_clearTagStateSet() throws Exception {
@@ -718,7 +750,7 @@ public void testFutureLessOneMin_clearTagStateSet() throws Exception {
freshTag.setPageContext(pageContext);
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testFutureLessOneHour() throws Exception {
@@ -740,7 +772,7 @@ public void testFutureLessOneHour() throws Exception {
freshTag.setPageContext(pageContext);
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testFutureLessOneHour_clearTagStateSet() throws Exception {
@@ -765,7 +797,7 @@ public void testFutureLessOneHour_clearTagStateSet() throws Exception {
freshTag.setPageContext(pageContext);
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testFutureLessOneYear() throws Exception {
@@ -787,7 +819,7 @@ public void testFutureLessOneYear() throws Exception {
freshTag.setPageContext(pageContext);
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testFutureLessOneYear_clearTagStateSet() throws Exception {
@@ -812,7 +844,7 @@ public void testFutureLessOneYear_clearTagStateSet() throws Exception {
freshTag.setPageContext(pageContext);
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testFutureTwoYears() throws Exception {
@@ -838,7 +870,7 @@ public void testFutureTwoYears() throws Exception {
freshTag.setPageContext(pageContext);
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testFutureTwoYears_clearTagStateSet() throws Exception {
@@ -867,7 +899,7 @@ public void testFutureTwoYears_clearTagStateSet() throws Exception {
freshTag.setPageContext(pageContext);
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testNoDateObjectInContext() throws Exception {
@@ -884,7 +916,7 @@ public void testNoDateObjectInContext() throws Exception {
freshTag.setPageContext(pageContext);
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testNoDateObjectInContext_clearTagStateSet() throws Exception {
@@ -904,7 +936,7 @@ public void testNoDateObjectInContext_clearTagStateSet() throws Exception {
freshTag.setPageContext(pageContext);
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(tag, freshTag));
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
/**
@@ -912,10 +944,8 @@ public void testNoDateObjectInContext_clearTagStateSet() throws Exception {
* since that tag does not have its own unit tests, and it also appears to be
* a broken tag. The code coverage tests can be moved if the tag is fixed, or
* removed if the tag is dropped.
- *
- * @throws Exception
*/
- public void testDateTextFieldTag_artificialCoverageTest() throws Exception {
+ public void testDateTextFieldTag_artificialCoverageTest() throws JspException {
final String format = "yyyy/MM/dd hh:mm:ss";
DateTextFieldTag dateTextFieldTag = createDateTextFieldTag();
dateTextFieldTag.setFormat(format);
@@ -939,20 +969,40 @@ public void testDateTextFieldTag_artificialCoverageTest() throws Exception {
freshTag.setPageContext(pageContext);
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
- strutsBodyTagsAreReflectionEqual(dateTextFieldTag, freshTag));
+ strutsBodyTagsAreReflectionEqual(dateTextFieldTag, freshTag));
+ }
+
+ public void testNewJava8Format() throws Exception {
+ String format = "EEEE MMMM dd, hh:mm a";
+ LocalDateTime now = LocalDateTime.now();
+ String formatted = DateTimeFormatter.ofPattern(format, ActionContext.getContext().getLocale()).format(now);
+ context.put("myDate", now);
+
+ tag.setName("myDate");
+ tag.setNice(false);
+ tag.setFormat(format);
+ tag.doStartTag();
+ tag.doEndTag();
+ assertEquals(formatted, writer.toString());
+
+ // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag().
+ DateTag freshTag = new DateTag();
+ freshTag.setPageContext(pageContext);
+ assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
+ "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
+ strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
/**
* Utility method to create a new {@link DateTextFieldTag} instance for code coverage tests.
- *
+ *
* Note: There is no datetextfield.ftl template for the tag, so it does not appear that it can
- * actually be used in practice. We can perform basic coverage tests from within this
- * unit test class until the {@link DateTextFieldTag} is fixed or removed.
- *
+ * actually be used in practice. We can perform basic coverage tests from within this
+ * unit test class until the {@link DateTextFieldTag} is fixed or removed.
+ *
* @return a basic {@link DateTextFieldTag} instance
- * @throws Exception
*/
- private DateTextFieldTag createDateTextFieldTag() throws Exception {
+ private DateTextFieldTag createDateTextFieldTag() {
DateTextFieldTag tag = new DateTextFieldTag();
tag.setPageContext(pageContext);
tag.setName("myDate");