Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring expression language (SpEL) not working on JPA/hibernate entity

Im trying to use a SpEL template to generate filename from entities. I have two entities that look similar to these:

@Entity
public class Invoice implements Serializable {
    private String invoicenumber;
    private Customer customer;

    @Column(name = "invoicenumber", nullable = false, length = 20)
    public String getInvoicenumber() {
        return this.invoicenumber;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "fk_customer", nullable = false)
    public Customer getCustomer() {
        return this.customer;
    }
}

@Entity
public class Customer implements Serializable {
    private String firstname;
    private String lastname;

    @Column(name = "firstname", nullable = false, length = 20)
    public String getFirstname() {
        return this.firstname;
    }

    @Column(name = "lastname", nullable = false, length = 20)
    public String getLastname() {
        return this.lastname;
    }
}

And a SpEL template similar to this one:

String template = "invoicenumber + '-' + customer.firstname + ' ' + customer.lastname";

Then i use SpEL to generate a filename from the template with an invoice object

public String generateFilename(String filenameTemplate, Object dataObject) {
    ExpressionParser parser = new SpelExpressionParser();
    Expression expression = parser.parseExpression(filenameTemplate);
    return expression.getValue(dataObject, String.class);
}

This test works:

String testTemplate = "invoicenumber + '-' + customer.firstname + ' ' + customer.lastname";
Invoice invoice = new Invoice();
invoice.setInvoicenumber("BF2016-06-ABCDEF");
invoice.setCustomer(new Customer());
invoice.getCustomer().setFirstname("Hans");
invoice.getCustomer().setLastname("Hansen");
assertEquals("BF2016-06-ABCDEF-Hans Hansen", generator.generateFilename(testTemplate, invoice));

This test doesn't:

Invoice invoice = invoiceRepository.findOne(4);

String template = "invoicenumber + '-' + customer.firstname + ' ' + customer.lastname";
String filename = filenameGenerator.generateFilename(template, invoice);
assertEquals("12344-201601-Heinrich Jahnke", filename);

This test actually results in "12344-201601-", which leads me to the assumption, that the hibernate proxies used for lazy loading the customer object are the problem. The firstname and lastname fields are null before they are loaded from the database, which would explain the rendered filename.

Any ideas on how to fix this? some things I already tried:

Hibernate.initialize(invoice);
Hibernate.initialize(invoice.getCustomer());
System.out.println(invoice.getCustomer().getFirstname());
  • Using "customer.getFirstname()" instead of "customer.firstname" in the expression
  • Adding @Transactional to my FilenameGenerator class
like image 995
Stefan Ortgies Avatar asked Jul 01 '16 13:07

Stefan Ortgies


1 Answers

The problem was somewhere else, SpEL and JPA/Hibernate are working fine together. Sorry for that!

My actual expression looked like this:

"invoicenumber + '-' + (customer.company == null ? customer.fname + ' ' + customer.sname : customer.company)"

Sadly the customer that was loaded from the database did have a company, an empty company... With following expression everything works out correctly:

"invoicenumber + '-' + (customer.company == null or customer.company.isEmpty() ? customer.fname + ' ' + customer.sname : customer.company)"
like image 60
Stefan Ortgies Avatar answered Oct 29 '22 15:10

Stefan Ortgies