1

We have a lot of code duplication in data holder classes that can be serialized to a XML string:

public String toXml() throws JAXBException {
    final JAXBContext context = JAXBContext.newInstance(this.getClass());
    final Marshaller marshaller = context.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
    final StringWriter stringWriter = new StringWriter();
    marshaller.marshal(this, stringWriter);
    return stringWriter.toString();
}

Why not move this code to a single interface with default implementation? So a simple implements ToXmlUtf8 would be enough to share the default implementation and avoid code duplicates:

public interface ToXml {
    default String toXml() throws JAXBException {
        final JAXBContext context = JAXBContext.newInstance(this.getClass());
        final Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
        final StringWriter stringWriter = new StringWriter();
        marshaller.marshal(this, stringWriter);
        return stringWriter.toString();
    }
}

Has anybody done this before successfully?

Other solutions?

I could also imagine using an annotation to generate this code.

Are there any ready to use solutions available?

AndreasL
  • 21
  • 2
  • Seems so. Have you created a small test to try it out? – Steve11235 May 29 '18 at 14:06
  • Would use a common parent class for that code, not a default method, see https://stackoverflow.com/q/26895604/995891 - or a utility method like `String toXml(Object object)` somewhere else. – zapl May 29 '18 at 14:08
  • The default interface solutions compiles, yes. – AndreasL May 29 '18 at 14:09
  • An abstract parent class restricts the class hierarchy. A Util class is not so nice for the caller with `Util.toXml(Object)` and Object as signature is ugly. At least use a marker interface. What are the arguments against the `default method`? I can't extract really arguments from the linked articles. Only that default methods were introduced for extending existing interfaces... – AndreasL May 29 '18 at 14:22
  • I'm not familiar with "default methods". What version of Java is this from? Can you add the appropriate tag to make it more obvious that this isn't available in older versions? – Code-Apprentice May 29 '18 at 14:38
  • Change tag to java-8 – AndreasL May 29 '18 at 15:02
  • @AndreasL “Object as signature is ugly”—why? The `Object` parameter signals that this method works with every input type whereas demanding the objects to implement a `ToXml` interface, whether a marker interface or having that `default` method, adds an entirely obsolete restriction. Be prepared to eventually meet the developers, who can’t use your code because they can’t force a 3rd party class to implement your interface that you just added for no reason, or well, just because “Object as signature is ugly”… – Holger May 29 '18 at 17:00

2 Answers2

3

Yes, default methods can be used in that way.

Although the intended use case of default methods is adding new functionality to existing interfaces without breaking old code, default methods have other uses as well. Default methods are also used in interfaces which were added in Java 8, such as in java.util.Predicate, so even the Java designers recognized that adding new functionality to existing interfaces is not the only valid use of default methods.

A disadvantage could be that the implemented interfaces are part of a class's public contract, but in your case this does not seem to be a problem.

Hoopje
  • 11,820
  • 6
  • 29
  • 47
2

If you're using the exact same method then an interface won't help, what you want to do is make a static method and put that in a util class

Sacha
  • 332
  • 1
  • 8
  • A Util class is not so nice for the caller with `Util.toXml(Object)` and Object as signature is ugly. At least use a marker interface. – AndreasL May 29 '18 at 14:23
  • I suggest you read about [default methods](https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html) to see how using an interface for this problem does actually help. – Code-Apprentice May 29 '18 at 14:40