[Geoserver-devel] [JIRA] (GEOS-8000) WPS process cleanup error - date paring error

Bjorn Nilsson created an issue

GeoServer / BugGEOS-8000

WPS process cleanup error - date paring error

Issue Type:

BugBug

Affects Versions:

2.9.3

Assignee:

Unassigned

Components:

WPS

Created:

21/Feb/17 2:47 PM

Environment:

OS Name Microsoft Windows Server 2008 R2 Standard
Version 6.1.7600 Build 7600

Java 1.8.0_73 x64
Tomcat 7.0.75 x64

geoserver-2.9.3
geoserver-2.9.3-wps-plugin

Bygginformation
Version
2.9.3
Git revision
0d588545aeb7550c04ce74ea8dbb932e3512f0dd
Byggdatum
24-Nov-2016 20:02
GeoTools-version
15.3 (rev 2db372589d85dfdc256a292f7cc11e8f81cdcdf2)
GeoWebCache-version
1.9.2 (rev 1.9.x/b259119a71b04329bd939d0ec791de997c5b0dbf)

Priority:

MediumMedium

Reporter:

Bjorn Nilsson

After successful execution of WPS processes the Geoserver Process status log in the UI fill up. No entries are ever deleted due to a date parsing error.

errors from geoserver log:

2017-02-21 11:33:01,253 DEBUG [geoserver.wps] - Removing statuses matching [[[ NOT [ completionTime IS NULL ] ] AND org.geotools.filter.temporal.BeforeImpl@anonymised.com] AND [[ NOT [ lastUpdated IS NULL ] ] AND org.geotools.filter.temporal.BeforeImpl@anonymised.com]]
2017-02-21 11:33:01,253 DEBUG [geotools.util] - InterpolationConverterFactory can be applied from Strings to Interpolation only.
2017-02-21 11:33:01,253 DEBUG [geotools.util] - CRSConverterFactory can be applied from Strings to CRS only.
2017-02-21 11:33:01,253 DEBUG [geotools.util] - InterpolationConverterFactory can be applied from Strings to Interpolation only.
2017-02-21 11:33:01,253 DEBUG [geotools.util] - CRSConverterFactory can be applied from Strings to CRS only.
2017-02-21 11:33:01,253 DEBUG [geotools.util] - InterpolationConverterFactory can be applied from Strings to Interpolation only.
2017-02-21 11:33:01,253 DEBUG [geotools.util] - CRSConverterFactory can be applied from Strings to CRS only.
2017-02-21 11:33:01,253 TRACE [geotools.util] - Error applying the converter class org.geotools.xml.XmlConverterFactory$XmlConverter on (Tue Feb 21 11:23:03 CET 2017,class java.util.Date)
java.lang.IllegalArgumentException: Failed to parse time Tue Feb 21 11:23:03 CET 2017 at:Tue Feb 21 11:23:03 CET 2017
at org.geotools.xml.impl.DatatypeConverterImpl.parseTime(DatatypeConverterImpl.java:189)
at org.geotools.xml.XmlConverterFactory$XmlConverter.convertFromString(XmlConverterFactory.java:123)
at org.geotools.xml.XmlConverterFactory$XmlConverter.convert(XmlConverterFactory.java:76)
at org.geotools.util.Converters.convert(Converters.java:168)
at org.geotools.util.Converters.convert(Converters.java:129)
at org.geotools.temporal.TemporalConverterFactory$2.convert(TemporalConverterFactory.java:51)
at org.geotools.util.Converters.convert(Converters.java:168)
at org.geotools.util.Converters.convert(Converters.java:129)
at org.geoserver.wps.property.BeanPropertyAccessor.get(BeanPropertyAccessor.java:37)
at org.geotools.filter.AttributeExpressionImpl.tryAccessor(AttributeExpressionImpl.java:248)
at org.geotools.filter.AttributeExpressionImpl.evaluate(AttributeExpressionImpl.java:208)
at org.geotools.filter.temporal.BinaryTemporalOperatorImpl.toInstant(BinaryTemporalOperatorImpl.java:64)
at org.geotools.filter.temporal.BinaryTemporalOperatorImpl.toTemporal(BinaryTemporalOperatorImpl.java:77)
at org.geotools.filter.temporal.BinaryTemporalOperatorImpl.evaluate(BinaryTemporalOperatorImpl.java:52)
at org.geotools.filter.AndImpl.evaluate(AndImpl.java:44)
at org.geotools.filter.AndImpl.evaluate(AndImpl.java:44)
at org.geoserver.wps.MemoryProcessStatusStore.remove(MemoryProcessStatusStore.java:74)
at org.geoserver.wps.executor.ProcessStatusTracker.cleanExpiredStatuses(ProcessStatusTracker.java:135)
at org.geoserver.wps.WPSStorageCleaner.run(WPSStorageCleaner.java:50)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.runAndReset(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
2017-02-21 11:33:01,253 DEBUG [geotools.util] - InterpolationConverterFactory can be applied from Strings to Interpolation only.
2017-02-21 11:33:01,253 DEBUG [geotools.util] - CRSConverterFactory can be applied from Strings to CRS only.
2017-02-21 11:33:01,253 DEBUG [geotools.util] - InterpolationConverterFactory can be applied from Strings to Interpolation only.
2017-02-21 11:33:01,253 DEBUG [geotools.util] - CRSConverterFactory can be applied from Strings to CRS only.

I wonder if this ever worked with java 8, but maybe I’m missing something. Below are some research from the code base:

According to the API doc for java 8 for java.util.Date

public String toString()

Converts this Date object to a String of the form:

dow mon dd hh:mm:ss zzz yyyy

This comment from the source below clearly states that a date string on the form:

dow mon dd hh:mm:ss zzz yyyy

would never be parsed correctly by this method

geotools/modules/extension/xsd/xsd-core/src/main/java/org/geotools/xml/impl/DatatypeConverterImpl.java

/** <p>Parses the lexical representation of the given dateTime value

  • and converts it into an instance of {@link java.util.Calendar}.

    • Valid lexical representations of a dateTime value include
    • <pre>
    • YYYY-MM-DDThh:mm:ss
    • YYYY-MM-DDThh:mm:ss.sss
    • YYYY-MM-DDThh:mm:ssZ
    • YYYY-MM-DDThh:mm:ss-01:00
    • </pre>
    • The former examples are all specified in UTC time. The last example
    • uses a negative offset of one hour to UTC.</p>
    • @param arg0 The input string being parsed.
    • @param lenient parameter used for allowing lenient parsing
    • @return The input string converted into an instance of
    • {@link java.util.Calendar}

    .

  • @see javax.xml.bind.ParseConversionEvent
    */
    public Calendar parseDateTime(String arg0, boolean lenient)
    Unknown macro: { XsDateTimeFormat format = new XsDateTimeFormat(); ParsePosition pos = new ParsePosition(0); Calendar cal = (Calendar) format.parseObject(arg0, pos, lenient); if (cal == null) { throw new IllegalArgumentException(“Failed to parse dateTime " + arg0 + " at:” + arg0.substring(pos.getErrorIndex())); } return cal; }

If we follow the stacktrace a bit furhter there seems to be an explicit to String cast in the XmlConverter.convert method.

geotools/modules/extension/xsd/xsd-core/src/main/java/org/geotools/xml/XmlConverterFactory.java

public class XmlConverterFactory implements ConverterFactory {

public Converter createConverter(Class source, Class target, Hints hints) {
// make sure either source or target is String in order not to step over
// TemporalConverterFactory
if (String.class.equals(target)) {
if (java.util.Date.class.isAssignableFrom(source)

Calendar.class.isAssignableFrom(source)) { return new XmlConverter(); }
} else if (String.class.equals(source)) {
if (java.util.Date.class.isAssignableFrom(target)
|| Calendar.class.isAssignableFrom(target)) { return new XmlConverter(); }

}
return null;
}

static class XmlConverter implements Converter {
public Object convert(Object source, Class target)
throws Exception {
if (String.class.equals(target))

{ return convertToString(source); }

return convertFromString((String) source, target);
}

private Object convertFromString(final String source, final Class<?> target) {

// don’t bother performing conversions if the target types are not dates/times
if(!Calendar.class.equals(target) && !Date.class.isAssignableFrom(target))
return null;

//JD: this is a bit of a hack but delegate to the
// commons converter in case we are executing first.
try {
Converter converter = new CommonsConverterFactory().createConverter(String.class,
target, null);

if (converter != null) {
Object converted = null;

try

{ converted = converter.convert(source, target); }

catch (Exception e)

{ //ignore }

if (converted != null)

{ return converted; }

}
}
catch(Exception e)

{ //fall through to jaxb parsing }

Calendar date;

//try parsing as dateTime
try {
try

{ date = DatatypeConverterImpl.getInstance().parseDateTime(source); }

catch(Exception e)

{ //try as just date date = DatatypeConverterImpl.getInstance().parseDate(source); }

} catch (Exception e)

{ //try as just time date = DatatypeConverterImpl.getInstance().parseTime(source); }

if (Calendar.class.equals(target))

{ return date; }

if (Date.class.isAssignableFrom(target)) {
Date time = date.getTime();

//check for subclasses
if (java.sql.Date.class.equals(target))

{ return new java.sql.Date(time.getTime()); }

if (Time.class.equals(target))

{ return new Time(time.getTime()); }

if (Timestamp.class.equals(target))

{ return new Timestamp(time.getTime()); }

return time;
}

return null;
}

private String convertToString(Object unconvertedValue) {
String textValue = null;

if (unconvertedValue instanceof Calendar)

{ Calendar cal = (Calendar) unconvertedValue; textValue = DatatypeConverterImpl.getInstance().printDateTime(cal); }

else if(unconvertedValue instanceof java.sql.Date){
DatatypeConverterImpl converter = DatatypeConverterImpl.getInstance();
Object hint = Hints.getSystemDefault(Hints.LOCAL_DATE_TIME_HANDLING);
Calendar cal;
if(Boolean.TRUE.equals(hint))

{ cal = Calendar.getInstance(); }

else

{ cal = Calendar.getInstance(TimeZone.getTimeZone(“GMT”)); }

cal.setTimeInMillis(((java.util.Date) unconvertedValue).getTime());
textValue = converter.printDate(cal);
} else if (unconvertedValue instanceof java.util.Date) {
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(“GMT”));
cal.setTimeInMillis(((java.util.Date) unconvertedValue).getTime());
DatatypeConverterImpl converter = DatatypeConverterImpl.getInstance();

if (unconvertedValue instanceof java.sql.Time)

{ textValue = converter.printTime(cal); }

else

{ // java.util.Date and java.sql.TimeStamp textValue = converter.printDateTime(cal); }

}

return textValue;
}
}

}

geotools/modules/library/main/src/main/java/org/geotools/temporal/TemporalConverterFactory.java

public class TemporalConverterFactory implements ConverterFactory {

static Converter dateToInstant = new Converter() {
public T convert(Object source, Class target) throws Exception

{ return (T) new DefaultInstant(new DefaultPosition((Date)source)); }

};

static Converter stringToInstant = new Converter() {

public T convert(Object source, Class target) throws Exception

{ //first go to java.util.Date Date d = Converters.convert(source, Date.class); //then go from date to instant return d != null ? dateToInstant.convert(d, target) : null; }

};

public Converter createConverter(Class<?> source, Class<?> target, Hints hints) {
if (Instant.class.isAssignableFrom(target)) {
if (Date.class.isAssignableFrom(source))

{ return dateToInstant; }

if (String.class.equals(source))

{ return stringToInstant; }

}

return null;
}
}

geoserver/src/extension/wps/wps-core/src/main/java/org/geoserver/wps/executor/ProcessStatusTracker.java

public void cleanExpiredStatuses(long expirationThreshold)

{ Date date = new Date(expirationThreshold); Not completionTimenotNull = FF.not(FF.isNull(FF.property(“completionTime”))); Filter completionTimeExpired = FF.before(FF.property(“completionTime”), FF.literal(date)); Filter completionTimeFilter = FF.and(completionTimenotNull, completionTimeExpired); Not lastUpdatedNotNull = FF.not(FF.isNull(FF.property(“lastUpdated”))); Filter lastUpdatedExpired = FF.before(FF.property(“lastUpdated”), FF.literal(date)); Filter lastUpdatedFilter = FF.and(lastUpdatedNotNull, lastUpdatedExpired); And filter = FF.and(completionTimeFilter, lastUpdatedFilter); store.remove(filter); }

geotools/modules/library/main/src/main/java/org/geotools/filter/FilterFactoryImpl.java

public Literal literal(Object obj) {
try

{ return new LiteralExpressionImpl(obj); }

catch (IllegalFilterException e)

{ new IllegalArgumentException().initCause(e); }

return null;
}

geotools/modules/library/main/src/main/java/org/geotools/filter/LiteralExpressionImpl.java

public LiteralExpressionImpl(Object literal)
throws IllegalFilterException

{ this.setValue(literal); }

public final void setValue(Object literal)

{ this.literal = literal; }

public Object getValue()

{ return literal; }

public String toString()

{ return literal == null ? “NULL” : literal.toString(); }

Add Comment

Add Comment

This message was sent by Atlassian JIRA (v1000.773.2#100032-sha1:6cd161b)

Atlassian logo