简体   繁体   中英

how to keep server side Java and client side JS DTO properties consistent

Hi I'm looking for a solution/plugin in Eclipse to keep server-side Java DTO properties and their client-side JSON counterparts consistent throughout the evolution of the codebase. For example, for a webapp with a Java backend, with APIs exposed through a REST interface (using Jackson), the webapp could have something like this on the server:

the DTO:

public class Person {
    private String firstName;
    private String lastName;
    public Person(String string, String string2) {
        firstName = string; lastName = string2;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

The REST Service:

@Path("/data")
public class PersonService {
    @GET
    @Path("persons")
    @Produces(MediaType.APPLICATION_JSON)
    public List<Person> getAssets() {
        List<Person> persons = new ArrayList<Person>();
        persons.add(new Person("Jimmy", "Hendrix"));
        persons.add(new Person("Roger", "Waters"));
        return persons;
    }
}

On the Client side, in Javascript/JQuery, we can have code like this:

$.ajax('/data/persons/', function(data){ for(var i = 0; i < data.length; i++){ var firstName = data[i].firstName; var lastName = data[i].lastName; //do some stuff to populate the view with the person data } });

This is all straightforward to set up. However, as the codebase evolves and changes (as it always does), suppose there is a need to change the names of the DTO fields from “firstName” and “lastName”, to “foreName”, and “surName”.

In Eclipse, refactoring all of the Java code is simple using the Refactor menu item, which will find ALL references of the method/field in the Java code, and replace them. Note that Eclipse's “Refactor…” is different than a Find/Replace action. Find/Replace does a basic text replace on all files specified. Refactor on the other hand, takes into account that Java is a strongly typed programming language, and searches for all method invocations with that signature.

It would be great if there was some plugin or Eclipse feature that would be smart enough to change the reference to “firstName” and “lastName” in the Javascript code as well. That would save developers the time of having to do a Refactor for just the Java code, and then a selective Find/Replace in the Javascript code, and reduce potential runtime errors. Does anyone know if such a tool/plugin exists?

Yeah, me too. This seems like a pattern I encounter at every job.

Best I've done in the past is generate Javascript stubs from the java DTOs and used JsDoc to indicate where those javascript DTOs are used.

If I was doing that same solution today, I'd probably see what Swagger codegen would give me out of the box.

Intellij at least will highlight missing fields in the javascript, which is helpful.

It would be great if there was a plugin, but this was better than nothing.

With typescript you'd even get compile safety with the stubs.

For the JavaScript snippet you presented in the question, such a tool is probably impossible to write.

However, there are things you can do to improve the situation.

On one side, you can write a generator for JavaScript representations of your DTOs. IDE-friendly strategy would be to generate objects that have properties with default values. Like

var Person = { firstName: "", lastName: "", roles:[] };

Even if you do not actively integrate such a file into the actual web UI, it helps to reduce typo errors by checking the warnings IDE will throw at you.

On another side, you could/should use a real JavaScript model layer. Then you can validate all DTO JavaScript representations during automated testing and/or with a special button in eg maintenance part of the UI that QA always verifies before release. If you upgrade your web UI together with the server, it definitely helps to catch missed refactoring leftovers.

Validation endpoint would receive a JSON object like this:

 { "Person": {...}, "Address": {...}, "Item": {...}, ... } 

and run it against package(s) with DTOs using a little bit of Java reflection. Of course, you could also use Nashorn engine in Java to do the validation directly on the server, eg during server start-up.

It is not a silver bullet, it just greatly helps to reduce errors. In the end, the less obscure logic you have in the UI, the easier it is to do the refactorings. Create or use generic, universal components, wire them up to DTOs in a very thin translation layer that uses label look-up tables, which can be validated as well. Also helps with i18n.

Generation and validation can be used separately or together in one project.

BTW, one of the reasons to choose GWT for UI layer some years ago was to achieve exactly what you want. I haven't been following it for a while, but it would be hard to imagine its drawbacks will outweigh this benefit.

There is no such plugin. Welcome to the world of languages that are not statically typed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM