3
\$\begingroup\$

I am trying to define some interfaces to implement some web service integration middleware. The SOA pattern that fits this system is probably the Multi-Channel Endpoint.

I expect a lot of mapping of data formats happening in this integration so I am trying to come up with some interfaces to implement this.

For each web service client I would like to provide a Service Facade that will map the input data to a common data structure (DTO) that will then be interpreted by the middleware which will orchestrate the services that connect to the legacy applications.

My attempt at coding the interfaces goes like this:

// Protocol for mapping POJOs to some Map-like data structure
public interface Dto {

    // Map from POJO fields to DtoData
    public DtoData toData();

    // Map from DtoData to POJO
    public void fromData(DtoData data);

}

public class DtoData {
    Map<String, Object> data;

    public Map<String, Object> getData() {
        return data;
    }

    public void setData(Map<String, Object> data) {
        this.data = data;
    }
}

// This class provides default mapping methods from POJOs to Maps.
// Uses Jackson and Dozer for mapping back and forth between objects.
// TODO use DI to create mapper objects.
public abstract class AbstractDto implements Dto {

    @Override
    public DtoData toData() {        
        ObjectMapper mapper = new ObjectMapper();
        DtoData map = mapper.convertValue(this, DtoData.class);
        return map;
    }

    @Override
    public void fromData(DtoData data) {
        DozerBeanMapper mapper = new DozerBeanMapper();
        mapper.map(data, this); 
    }

}

public class DtoImpl extends AbstractDto implements Dto {

    private DtoData dtoData;

    public DtoData getDtoData() {
        return dtoData;
    }

    public void setDtoData(DtoData dtoData) {
        this.dtoData = dtoData;
    }

}

Any suggestions on how to improve this and pitfalls that I can expect?

\$\endgroup\$
1
\$\begingroup\$

I am not sure I understand what's the reason of your Dto and of its AbstractDto and DtoImpl implementations. Why does it need to hold a dtoData instance? I think that you should separate the definition of Dtos, the definition of DtoData and the definition of a Mapper that translates between the two representation.

I think you should't really have a Dto interface or leave it to be just a marker interface, but I don't really like them as they are usually an anti pattern.

I don't like that you pass directly a Map to your DtoData. What about something implementing this (very Map-like) interface?

interface DtoData
{
    void setValue(String key, object value);
    void getValue(String key, object value);
    Set<String> getKeys();
}

Finally all the conversions should be handled by a Mapper, implementing this interface.

inteface Mapper
{
    Object toDto(DtoData dtoData);
    DtoData toDtoData(Object dto);
}

If you organise your program in this way you have different pieces that cover different responsibilities and it should be trival to change format of DtoData and the way you map them.

One possible improvement over that would be to let the compiler help you putting everything together in the right way. You can do that by rewriting Mapper such that it is generic. Something like Mapper<T,K>.

\$\endgroup\$
  • \$\begingroup\$ I think my design is confusing and I can't even explain what is the purpose of a Dto as I defined it except that I wanted some way to represent the mapping of POJOs to an associative data structure. Your DtoData interface is very similar to java.util.Map then why not use it directly? If I understood correctly, in your design what matters is the Mapper interface which translates a generic entity (Object or Dto) to some Map-like interface. \$\endgroup\$ – dmz73 Oct 2 '14 at 22:06
  • \$\begingroup\$ Exactly. Wrapping the map in another object could be useful if you want to add some sort of validation of its content. Another reason is that you could make it clear with the type that what you have is a map with a specific meaning. If you don't need that maybe it's better to keep it simple and use a map directly. \$\endgroup\$ – mariosangiorgio Oct 2 '14 at 22:17
  • \$\begingroup\$ Why is DTO an anti pattern? What are the advantages of making Mapper generic with Mapper<T,K>? Should I make a marker interface for the Object that I am trying to map. These objects will be service inputs or service outputs in my application. From what I read, marker interfaces are obsolete and annotations should be used instead. \$\endgroup\$ – dmz73 Oct 3 '14 at 4:05
  • \$\begingroup\$ Another idea would be to rename the DtoData interface to Dto and define it as interface Dto extends Map<String, Object> {}. \$\endgroup\$ – dmz73 Oct 3 '14 at 4:19
  • \$\begingroup\$ I said that marker interfaces are antipatterns, not DTOs. If you don't need any method to be implemented why do you need an interface? Extending map is not a really good idea. Search for "prefer composition over inheritance" to read why \$\endgroup\$ – mariosangiorgio Oct 3 '14 at 6:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.