I want to share the very same Java types for an API server and an API client. It seems I cannot use an abstract interface Pet to type a field of a controller method parameter @ModelAttribute Family family .

What I tried - Searched for annotations like Jackson @JsonDeserialize(as = ...): none exists - Custom ConversionService: not called for initializing nested bean properties by BeanWrapperImpl - Custom WebDataBinder: overkill

Full test case:

public interface Pet { String getName(); }

public static class Family {
    private Pet pet;
    public Pet getPet() { return pet; }
    public void setPet(Pet pet) { this.pet = pet; }
}

public static class Dog implements Pet {
    private String name;
    public String getName() {return name; }
    public void setName(String name) { this.name = name;}
}

@RestController
public static class PetController {
    @PostMapping("/family")
    public String createFamily(@ModelAttribute Family family) {
        return "Created family with pet " + family.getPet().getName();
    }
}

private MockMvc mockMvc;

@BeforeEach
public void setUp() {
    mockMvc = MockMvcBuilders.standaloneSetup(new PetController())
            .build();
}

@Test
public void testPetControllerCreateFamily() throws Exception {
    mockMvc.perform(post("/family")
            .contentType(MediaType.APPLICATION_FORM_URLENCODED)
            .param("pet.name", "Fido"))
            .andExpect(status().isOk())
            .andExpect(content().string("Created family with pet Fido"));
}

Comment From: snicoll

Thanks for the suggesting but that sounds pretty logical to me given that we don't have any information about the type that should actually be created. Guessing is a bad idea so we won't do that.

For any follow-up as to how you could potentially implement something like this, follow on StackOverflow.