Question

Im using custom editor in Spring MVC to map string valuest to my domain objects. Simple case: User object refers to Company (User.company -> Company). In User form I register data binder:

protected void initBinder(WebDataBinder binder) throws Exception {
    binder.registerCustomEditor(Company.class, new CompanyEditor(appService));
}

Editor is defined as folows:

class CompanyEditor extends PropertyEditorSupport {

    private AppService appService;  

    public CompanyEditor(AppService appService) {
        this.appService = appService;
    }

    public void setAsText(String text) {
        Company company = appService.getCompany(text);
        setValue(company);
    }

    public String getAsText() {
        Company company = (Company) this.getValue();
        if (company != null)
            return company.getId();
        return null;
    }    
}

When I use dropdown in my form

<form:select path="company">
    <form:options items="${companies}" itemLabel="name" itemValue="id"/>
</form:select>

I experience severe performance problems because (to check if company is selected, I suppose) fires setAsText and getAsText for each option, which makes it to run a SQL query for each company.

I thought that setAsText is used when I commit form to make application know how to translate compnany id to Company (persisted) object. Why should it fire it in dropdowns. Any ideas how to fix it?

Was it helpful?

Solution

If your form backing object is stored as session attribute(i.e. you have something like @SessionAttributes("command") in your controller), so you can try to modify your setAsText(String text) method

public void setAsText(String text) {
        Company currentCompany = (Company) this.getValue();
        if ((currentCompany != null) && (currentCompany.getId().equals(text)))
          return;

        Company company = appService.getCompany(text);
        setValue(company);
    }

but I think that Spring 3.1 @Cacheable abstraction was introduced exactly for the such kind of things and is preferable

see examples in documentation

@Cacheable("books")
public Book findBook(ISBN isbn) {...}

P.S. Consider using new Converter SPI instead of Property Editors.

In general, it's possible to implement a generic converter for your look-up entities, so it will automatically convert entities from text using id if they have some specific attribute, for example, in one of my projects all @Entity types are being automatically converted using a global ConditionalGenericConverter implementation, so I neither register custom property editors during binding nor implement specific converters for types which are simple @Entity classes with @Id annotated primary keys.

Also it's very convenient when Spring automatically converts textual object ids to the actual entities when they are specified as @RequestParam annotated controller method arguments.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top