RSS 2.0
Sign In
# Wednesday, 24 January 2018

J2SE has become sole large that its different parts don't play well.

That is pitty but nothing to do. There is probably a lack of resources in Oracle to fill gaps.

So, to the point.

There is relatively new API to work with time defined in: package java.time. There is older API JAXB to serialize and deserialize beans to and from XML (and often to JSON). To JAXB viable, it should be able to deal with basic primitive types. The problem is that JAXB does not handle LocalDate, LocalTime, LocalDateTime, and ZonedDateTime out of the box.

We do understand that:

  • JAXB is older and java.time is newer API; and that
  • JAXB has no built-in plugin to handle new types.

But this does not help, and we should define/redefine serialization adapters using some drop in code or third party libraries. Here are these convenience adapters:

LocalDateAdapter.java

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;

import javax.xml.bind.annotation.adapters.XmlAdapter;

/**
 * An adapter for the bean properties of {@link LocalDate} type. 
 */
public class LocalDateAdapter extends XmlAdapter<String, LocalDate>
{
  /**
   * Converts {@link LocalDate} into a string value.
   * @param value a value to convert. Can be null.
   * @return a string value.
   */
  @Override
  public String marshal(LocalDate value)
    throws Exception
  {
    return value == null ? null : value.toString();
  }

  /**
   * Converts a string value into a {@link LocalDate}
   * instance.
   * @param value a value to convert. Can be null.
   * @return a {@link LocalDate} instance.
   */
  @Override
  public LocalDate unmarshal(String value)
    throws Exception
  {
    if (value == null)
    {
      return null;
    }
    
    int p = value.indexOf('T');
    
    if (p < 0)
    {
      return LocalDate.parse(value);
    }
    
    while(++p < value.length())
    {
      switch(value.charAt(p)) 
      {
        case '+':
        case '-':
        case 'Z':
        {
          return ZonedDateTime.parse(value).toLocalDate();
        }
      }
      
    }
    
    return LocalDateTime.parse(value).toLocalDate();
  }
}

LocalDateTimeAdapter.java

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZonedDateTime;

import javax.xml.bind.annotation.adapters.XmlAdapter;

/**
 * An adapter for the bean properties of {@link LocalDateTime} type. 
 */
public class LocalDateTimeAdapter extends XmlAdapter<String, LocalDateTime>
{
  /**
   * Converts {@link LocalDateTime} into a string value.
   * @param value a value to convert. Can be null.
   * @return a string value.
   */
  @Override
  public String marshal(LocalDateTime value)
    throws Exception
  {
    return value == null ? null : value.toString();
  }

  /**
   * Converts a string value into a {@link LocalDateTime}  instance.
   * @param value a value to convert. Can be null.
   * @return a {@link LocalDateTime} instance.
   */
  @Override
  public LocalDateTime unmarshal(String value) 
    throws Exception
  {
    if (value == null)
    {
      return null;
    }
    
    int p = value.indexOf('T');
    
    if (p < 0)
    {
      return LocalDateTime.of(LocalDate.parse(value), LocalTime.MIN);
    }
    
    while(++p < value.length())
    {
      switch(value.charAt(p)) 
      {
        case '+':
        case '-':
        case 'Z':
        {
          return ZonedDateTime.parse(value).toLocalDateTime();
        }
      }
      
    }
    
    return LocalDateTime.parse(value);
  }
}

LocalTimeAdapter.java

import java.time.LocalDate;import java.time.LocalTime;

import javax.xml.bind.annotation.adapters.XmlAdapter;

/**
 * An adapter for the bean properties of {@link LocalTime} type. 
 */
public class LocalTimeAdapter extends XmlAdapter<String, LocalTime>
{
  /**
   * Converts {@link LocalTime} into string value.
   * @param value a value to convert. Can be null.
   * @return a string value
   */
  @Override
  public String marshal(LocalTime value)
    throws Exception
  {
    return value == null ? null : value.toString();
  }

  /**
   * Converts a string value into a {@link LocalTime} instance.
   * @param value a value to convert. Can be null.
   * @return a {@link LocalTime} instance.
   */
  @Override
  public LocalTime unmarshal(String value)
    throws Exception
  {
    return value == null ? null : LocalTime.parse(value);
  }
}

To make them work either field/properties or package should be annotated with JAXB xml adapters.

The simplest way is to annotate it on package level like this:

package-info.java

@XmlJavaTypeAdapters(
{
  @XmlJavaTypeAdapter(value = LocalDateAdapter.class, type = LocalDate.class),
  @XmlJavaTypeAdapter(value = LocalTimeAdapter.class, type = LocalTime.class),
  @XmlJavaTypeAdapter(value = LocalDateTimeAdapter.class, type = LocalDateTime.class)
})
package com.nesterovskyBros.demo.entities;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
Wednesday, 24 January 2018 06:46:41 UTC  #    Comments [0] -
Java | Tips and tricks
Comments are closed.
Archive
<2018 June>
SunMonTueWedThuFriSat
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567
Statistics
Total Posts: 357
This Year: 2
This Month: 1
This Week: 0
Comments: 222
Locations of visitors to this page
Disclaimer
The opinions expressed herein are our own personal opinions and do not represent our employer's view in anyway.

© 2018, Nesterovsky bros
All Content © 2018, Nesterovsky bros
DasBlog theme 'Business' created by Christoph De Baene (delarou)