Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serializing Collator instance

I am trying to serialize some objects of class InstitutionResultView which is basically wrapper to guava's TreeMultimap:

import java.io.Serializable;
import java.text.Collator;
import java.util.Comparator;

import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.collect.Maps.EntryTransformer;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.Ordering;
import com.google.common.collect.SortedSetMultimap;
import com.google.common.collect.TreeMultimap;

public class InstitutionResultView implements Serializable {
  private static final long serialVersionUID = -8110992296090587657L;

  private final SortedSetMultimap<String, Institution> nameToInstitutionsMapping = TreeMultimap.create(
      Ordering.from(StringComparators.AS_IS), // insertion order
      Ordering.natural() // <----- this works when serializing object
      // Ordering.from(Collator.getInstance()) // <----- when used instead previous line gives an exception when serializing
          .nullsFirst().onResultOf(StringInstitutionFunctions.BY_NAME) // sort by name
          .compound(
              Ordering.natural().nullsFirst().onResultOf(IntegerInstitutionFunctions.BY_ID) // sort by id
              ));

  public SortedSetMultimap<String, Institution> institutions() {
    return nameToInstitutionsMapping;
  }

  public void setInstitutions(final Multimap<String, Institution> institutions) {
    this.nameToInstitutionsMapping.clear();
    this.nameToInstitutionsMapping.putAll(institutions);
  }

  @Override
  public String toString() {
    return Objects.toStringHelper(this)
        .add("nameToInstitutionsMapping", Multimaps.transformEntries(nameToInstitutionsMapping, EntryTransformers.TO_NAME_WITH_CATEGORY))
        .toString();
  }

During serialization I get exception:

java.io.NotSerializableException: java.text.RuleBasedCollator at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164) at

...

com.google.common.collect.TreeMultimap.writeObject(TreeMultimap.java:180)

...

I found this bug from Sun's bug database which covers very similar case to mine, but it doesn't point to any resolution. I tried adding transient Collator instance field:

  private transient Collator collatorInstance = Collator.getInstance();

and using it as Ordering.from(collatorInstance) but still it doesn't work.

I'd be glad if anybody could give me some idea what to do to solve this problem.


EDIT - That's what worked for me (thanks to @Puce and his answer):

  class CollatorWrapper implements Comparator<String>, Serializable {
    private static final long serialVersionUID = 1L;

    private transient Collator collatorInstance;

    public CollatorWrapper() {
      super();
      initCollatorInstance();
    }

    @Override
    public int compare(final String o1, final String o2) {
      return collatorInstance.compare(o1, o2);
    }

    private void initCollatorInstance() {
      collatorInstance = Collator.getInstance();
    }

    private void writeObject(final java.io.ObjectOutputStream out) throws IOException {
      out.defaultWriteObject();
    }

    private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
      in.defaultReadObject();
      initCollatorInstance();
    }
  }
like image 207
Xaerxess Avatar asked May 28 '26 20:05

Xaerxess


1 Answers

I think you might be able to write a wrapper, which

  • implements Comparator
  • implements Serialzable (and the necessary methods such as readObject, writeObject)
  • wraps a transient Collator
  • remembers the Locale (if you need that)
like image 153
Puce Avatar answered May 31 '26 10:05

Puce



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!