0

So my problem is the following: For an application that I need to write I have to implement the ability to store some DTOs to disk to be reused later on (in JSON format). Just to give you a broad frame of reference: The DTOs contain process/data models and also their graphical representation.

To obtain the desired JSON files I currently use Jackson. This works out fine for the largest part, however, in one object that needs to be saved I use a ResourceBundle (to localize the program for different languages). And this is exactly where the problem comes in, as Jackson seems to be unable to serialize ResourceBundle objects (know that both from trying it, but also the research I have done so far basically told me the same).

So I would like to ask you whether you might have an idea how to make it work, or whether you might have found some fancy workaround.

For further illustration I will append some sample code which is not from the project in question, since I do this for someone else and I am not sure whether he would appreciate the release of his code.

public class SomeClass {
  private String name;
  private ResourceBundle bundle;

  public SomeClass(String name, ResourceBundle bundle) {
    this.name = name;
    this.bundle = bundle;
  }

  public String getName() {
    return this.name;
  }

  public ResourceBundle getBundle() {
    return this.bundle;
  }

  public void setName(String name) {
    this.name = name;
  }

  public void setBundle(ResourceBundle bundle) {
    this.bundle = bundle;
  }

  /*
    Here one could imagine some additional functionality making use of the 
    given ResourceBundle (something that has to be printed depending on the
    used language etc.). 
  */
}
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;
import java.util.ResourceBundle;

public class Saver {

  public static void main(String[] args) {
    Saver saver = new Saver();
    saver.run();
  }

  public void run() {
    ObjectMapper om = new ObjectMapper();
    ResourceBundle rb = ResourceBundle.getBundle("test");
    SomeClass sc = new SomeClass("SomeClass", rb);
    try {
      om.writeValue(new File("test.json"), sc);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

The resulting Stack Trace looks as follows:

com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class sun.util.ResourceBundleEnumeration and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: SomeClass["bundle"]->java.util.PropertyResourceBundle["keys"])
  at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:230)
  at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:68)
  at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:32)
  at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:672)
  at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:678)
  at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157)
  at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:672)
  at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:678)
  at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157)
  at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:130)
  at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:3613)
  at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2929)
  at Saver.run(Saver.java:22)
  at Saver.main(Saver.java:14)
Marco N.
  • 185
  • 2
  • 8
  • 2
    Why? You don't need to serialize ResourceBundles. They're static data and they're already in an external file. Make the field transient. – user207421 Mar 02 '16 at 19:09
  • Well, I just tried that. It did not fix the issue. If I add `@JsonIgnore` and `@JsonProperty` annotations (as mentioned here: http://stackoverflow.com/questions/9112900/jackson-how-to-prevent-field-serialization) the error goes away. One issue that remains is that I am unsure of how to get back access to the bundle when I load the file after e.g. restarting the program. Might be that I am just getting something wrong or that I do miss the obvious. Thats why I would appreciate further hints. (I already spend more than 2 hours with a colleague trying to solve this, so I am not just lazy). – Marco N. Mar 02 '16 at 19:17
  • I have to go or I might do an example... You could try to store the filename and serialize/deserialize that, then in the get ResourceBundle do a null check and instantiate if you have the filename. Alternatively, you could make a customer serializer/deserializer. You would probably need a custom ResourceBundle implementation as well... – Aaryn Tonita Mar 02 '16 at 19:21
  • Many thanks! The String solution already seems to fulfill the requirements I have. Sometimes there is such a simple and elegent solution to a problem but I tend to always miss them. If you would make this a real answer I would gladly accept it as the official solution. – Marco N. Mar 02 '16 at 19:39

1 Answers1

0

You should check your JSON Java class, if it contains a recursive cycle that may blow up your application. If this is the case add @JsonIgnore to the relevant attribute to break the cycle.

Zouhair Kasmi
  • 614
  • 2
  • 6
  • 13