Change listener for a specific field

Hi, i have database ContratosProductos, and i’ve been created a entitylistener for that tablet.

Problem is, i would like to execute a function, only when Field Producto (entity related), has changed or inserted, and put name of producto (from entity producto) to field Nombre on Entity ContratosProductos .

This is my Code, anyone can help me please?


package com.company.contratos.listener;

import org.springframework.stereotype.Component;
import com.haulmont.cuba.core.listener.AfterInsertEntityListener;
import com.company.contratos.entity.Productos;
import com.haulmont.cuba.core.listener.AfterUpdateEntityListener;

import javax.inject.Inject;

@Component("contratos_ListennerContratosProductos")
public class ListennerContratosProductos implements AfterInsertEntityListener<Productos>, AfterUpdateEntityListener<Productos> {
    
    public void onAfterInsert(Productos entity) {
    }
    
    @Override
    public void onAfterUpdate(Productos entity) {

    }
}

Then you have to do it in the screen controller. You can add listeners to the entity instance itself (every entity has addPropertyChangeListener() / removePropertyChangeListener() methods) or to the datasource that holds the instance (addItemPropertyChangeListener() / removeItemPropertyChangeListener()).
See Datasource Listeners - CUBA Platform. Developer’s Manual

For example, you have the Product and OrderLine entities. OrderLine has a reference to Product and a text field Description that you want to populate depending on selected Product. Then you can create the following entity listener on OrderLine:

package com.company.sales.listener;

import com.haulmont.cuba.core.PersistenceTools;
import org.springframework.stereotype.Component;
import com.haulmont.cuba.core.listener.BeforeInsertEntityListener;
import com.company.sales.entity.OrderLine;
import com.haulmont.cuba.core.listener.BeforeUpdateEntityListener;

import javax.inject.Inject;

@Component("sales_OrderLineEntityListener")
public class OrderLineEntityListener implements BeforeInsertEntityListener<OrderLine>, BeforeUpdateEntityListener<OrderLine> {

    @Inject
    private PersistenceTools persistenceTools;

    @Override
    public void onBeforeInsert(OrderLine entity) {
        updateDescription(entity);
    }

    @Override
    public void onBeforeUpdate(OrderLine entity) {
        updateDescription(entity);
    }

    private void updateDescription(OrderLine orderLine) {
        if (persistenceTools.isDirty(orderLine, "product")) {
            orderLine.setDescription("Product name: " + orderLine.getProduct().getName());
        }
    }
}

See also this topic: cuba platform - Create Entity by using EntityListener - Stack Overflow

i’ve created a Listenner for a Entity, but not working.

This is the code :frowning:


package com.company.contratos.listener;

import org.springframework.stereotype.Component;
import com.haulmont.cuba.core.listener.AfterInsertEntityListener;
import com.haulmont.cuba.core.listener.AfterUpdateEntityListener;
import com.haulmont.cuba.core.PersistenceTools;

import javax.inject.Inject;
import com.company.contratos.entity.ContratosProductos;

import java.math.BigDecimal;

/**
 * @author Grupimaticaivan
 */
@Component("contratos_ListennerContratosProductos")
public class ListennerContratosProductos implements AfterInsertEntityListener<ContratosProductos>, AfterUpdateEntityListener<ContratosProductos> {

    @Inject
    private PersistenceTools persistenceTools;

    @Override
    public void onAfterInsert(ContratosProductos entity) {
        updateCampos(entity);
    }

    @Override
    public void onAfterUpdate(ContratosProductos entity) {
        updateCampos(entity);
    }

    private void updateCampos(ContratosProductos contratosProductos) {
        contratosProductos.setUnidades(new BigDecimal("100"));
        if (persistenceTools.isDirty(contratosProductos, "producto")){
            contratosProductos.setNombre(contratosProductos.getProducto().getNombre());
        }
    }
}

Don’t use After* listeners, use Before* listeners instead.
Read about differences in listeners in the documentation and here.

Hi, this one works when i clic on OK (SAVE) buttton on Screen.

I need to get the change Before Save, when i change Producto (related table).

Ok, i’ve Used a Property of Screen to see if Producto is not null, and nombre is null to put values in fields. maybe, exits a best mode to detect an especific field, but we are going quickly with this smallest App.

Ok, now, i need to in line:

contratosProductosDs.getItem().setPrecio(contratosProductosDs.getItem().getProducto().getPrecio());

getPrecio is a related database from Producto, with a Field (NIVEL_SERVICIO) , Field (PRICE) and, Field (PRODUCT_ID --> RELATED WITH TABLE producto).

i Have a FIELD NIVEL SERVICIO in contratosProductosDs .

How can i retrieve, PRICE from TABLE Precio based on PRODUCT ID and NIVEL SERVICIO from contratosProductosDs ¿?


/*
 * Copyright (c) 2016 Contratos
 */
package com.company.contratos.gui.contratosproductos;

import com.haulmont.cuba.gui.components.AbstractEditor;
import com.company.contratos.entity.ContratosProductos;
import com.haulmont.cuba.gui.data.Datasource;
import javax.inject.Inject;
import java.math.BigDecimal;
import java.util.Map;
import java.util.UUID;

/**
 * @author Grupimaticaivan
 */
public class ContratosProductosEdit extends AbstractEditor<ContratosProductos> {
    @Inject
    private Datasource<ContratosProductos> contratosProductosDs;

    @Override
    public void init(Map<String, Object> params) {
        contratosProductosDs.addItemChangeListener( e -> calculartotallinea());
        contratosProductosDs.addItemPropertyChangeListener(e -> calculartotallinea());
    }

    private void  calculartotallinea() {
        if (contratosProductosDs.getItem().getProducto() != null && contratosProductosDs.getItem().getNombre() == null){
            contratosProductosDs.getItem().setNombre(contratosProductosDs.getItem().getProducto().getNombre());
            contratosProductosDs.getItem().setPrecio(contratosProductosDs.getItem().getProducto().getPrecio());
        }

        if (contratosProductosDs.getItem().getNombre() != null && (contratosProductosDs.getItem().getUnidades() != null) && (contratosProductosDs.getItem().getDto() != null) && (contratosProductosDs.getItem().getPrecio() != null)) {
            /*showNotification(getMessage("selectBook.text"), NotificationType.HUMANIZED);*/
            BigDecimal totallinea = BigDecimal.ZERO;
            BigDecimal importelinea = BigDecimal.ZERO;
            BigDecimal importedescuento = BigDecimal.ZERO;

            importelinea = contratosProductosDs.getItem().getUnidades().multiply(getItem().getPrecio());

            BigDecimal porcentaje, dto, cero ;
            porcentaje = new BigDecimal("100");
            cero = new BigDecimal("0");
            dto = getItem().getDto();
            importedescuento = importelinea.divide(porcentaje).multiply(dto);

            totallinea = importedescuento;
            totallinea = importelinea.subtract(importelinea.divide(porcentaje).multiply(dto));

            getItem().setImporte(totallinea);
        }
    }

}

Try to think in terms of object graphs, not database relations.
If you mapped your entities in such way that Producto has a reference to Precio, and Precio has Price attribute, you can get price as follows:
producto.getPrecio().getPrice().
Of course the whole object graph must be loaded from the database. You can achieve this by using an appropriate view in a datasource or when invoking DataManager or Query programmatically.

i’ve added Datamanager but with no results :frowning:


/*
 * Copyright (c) 2016 Contratos
 */
package com.company.contratos.gui.contratosproductos;

import com.haulmont.cuba.core.global.LoadContext;
import com.haulmont.cuba.gui.components.AbstractEditor;
import com.company.contratos.entity.ContratosProductos;
import com.company.contratos.entity.ProductosPrecios;
import com.haulmont.cuba.gui.data.Datasource;
import javax.inject.Inject;
import java.math.BigDecimal;
import java.util.Map;
import java.util.UUID;
import java.sql.*;

/**
 * @author Grupimaticaivan
 */
public class ContratosProductosEdit extends AbstractEditor<ContratosProductos> {
    @Inject
    private Datasource<ContratosProductos> contratosProductosDs;
    private Datasource<ProductosPrecios> ProductosPreciosDs;

    @Override
    public void init(Map<String, Object> params) {
        contratosProductosDs.addItemChangeListener( e -> calculartotallinea());
        contratosProductosDs.addItemPropertyChangeListener(e -> calculartotallinea());
    }

    private void  calculartotallinea() {
        if (contratosProductosDs.getItem().getProducto() != null && contratosProductosDs.getItem().getNombre() == null){
            contratosProductosDs.getItem().setNombre(contratosProductosDs.getItem().getProducto().getNombre());
            LoadContext(ProductosPrecios) context = LoadContext.create(ProductosPrecios.class).setQuery(
                    LoadContext.createQuery("select pp from app$ProductosPrecios pp where pp.Producto.id = :productid and pp.servicelevel = :serviceLevel")
                            .setParameter("productid",contratosProductosDs.getItem().getProducto().getId())
                            .setParameter("serviceLevel","High"));
            ProductosPrecios pp = dataManager.load(context);
            BigDecimal price = pp.getPrecio();
            contratosProductosDs.getItem().setPrecio(price)

        }

        if (contratosProductosDs.getItem().getNombre() != null && (contratosProductosDs.getItem().getUnidades() != null) && (contratosProductosDs.getItem().getDto() != null) && (contratosProductosDs.getItem().getPrecio() != null)) {
            /*showNotification(getMessage("selectBook.text"), NotificationType.HUMANIZED);*/
            BigDecimal totallinea = BigDecimal.ZERO;
            BigDecimal importelinea = BigDecimal.ZERO;
            BigDecimal importedescuento = BigDecimal.ZERO;

            importelinea = contratosProductosDs.getItem().getUnidades().multiply(getItem().getPrecio());

            BigDecimal porcentaje, dto, cero ;
            porcentaje = new BigDecimal("100");
            cero = new BigDecimal("0");
            dto = getItem().getDto();
            importedescuento = importelinea.divide(porcentaje).multiply(dto);

            totallinea = importedescuento;
            totallinea = importelinea.subtract(importelinea.divide(porcentaje).multiply(dto));

            getItem().setImporte(totallinea);
        }
    }

    private void buscarprecio(BigDecimal precio) {
        Integer levelofservice;
        UUID productoid;
        BigDecimal precioproducto = BigDecimal.TEN;
        levelofservice = contratosProductosDs.getItem().getContrato().getNivelServicio().getId();
        productoid = contratosProductosDs.getItem().getProducto().getId();
        precioproducto = ProductosPreciosDs.getItem().getPrecio();
        return;
        /*Statement stmt = conn.createStatement();
        ResultSet rs = stmt.("SELECT Lname FROM Customers WHERE Snum = 2001");*/
    }

}

I put Correct CODE :slight_smile:

Thanks for your help Konstantin, are you the best!


/*
 * Copyright (c) 2016 Contratos
 */
package com.company.contratos.gui.contratosproductos;

import com.haulmont.cuba.core.global.LoadContext;
import com.haulmont.cuba.gui.components.AbstractEditor;
import com.company.contratos.entity.ContratosProductos;
import com.company.contratos.entity.ProductosPrecios;
import com.haulmont.cuba.gui.data.Datasource;
import javax.inject.Inject;
import java.math.BigDecimal;
import java.util.Map;
import java.util.UUID;
import java.sql.*;

import com.haulmont.cuba.core.global.DataManager;
import com.haulmont.cuba.core.global.LoadContext;
import com.haulmont.cuba.core.global.Metadata;
import com.haulmont.cuba.core.global.View;
import com.haulmont.cuba.gui.components.*;
import com.haulmont.cuba.gui.data.CollectionDatasource;

import javax.inject.Inject;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * @author Grupimaticaivan
 */
public class ContratosProductosEdit extends AbstractEditor<ContratosProductos> {
    @Inject
    private Datasource<ContratosProductos> contratosProductosDs;
    private Datasource<ProductosPrecios> ProductosPreciosDs;

    @Inject
    private DataManager dataManager;

    @Override
    public void init(Map<String, Object> params) {
        contratosProductosDs.addItemChangeListener( e -> calculartotallinea());
        contratosProductosDs.addItemPropertyChangeListener(e -> calculartotallinea());
    }

    private void  calculartotallinea() {
        if (contratosProductosDs.getItem().getProducto() != null && contratosProductosDs.getItem().getNombre() == null){
            contratosProductosDs.getItem().setNombre(contratosProductosDs.getItem().getProducto().getNombre());
            LoadContext<ProductosPrecios> context = LoadContext.create(ProductosPrecios.class).setQuery(
                    LoadContext.createQuery("select pp from app$ProductosPrecios pp where pp.Producto.id = :productid and pp.servicelevel = :serviceLevel")
                            .setParameter("productid",contratosProductosDs.getItem().getProducto().getId())
                            .setParameter("serviceLevel","High"));
            ProductosPrecios pp = dataManager.load(context);
            BigDecimal price = pp.getPrecio();
            contratosProductosDs.getItem().setPrecio(price);

        }

        if (contratosProductosDs.getItem().getNombre() != null && (contratosProductosDs.getItem().getUnidades() != null) && (contratosProductosDs.getItem().getDto() != null) && (contratosProductosDs.getItem().getPrecio() != null)) {
            /*showNotification(getMessage("selectBook.text"), NotificationType.HUMANIZED);*/
            BigDecimal totallinea = BigDecimal.ZERO;
            BigDecimal importelinea = BigDecimal.ZERO;
            BigDecimal importedescuento = BigDecimal.ZERO;

            importelinea = contratosProductosDs.getItem().getUnidades().multiply(getItem().getPrecio());

            BigDecimal porcentaje, dto, cero ;
            porcentaje = new BigDecimal("100");
            cero = new BigDecimal("0");
            dto = getItem().getDto();
            importedescuento = importelinea.divide(porcentaje).multiply(dto);

            totallinea = importedescuento;
            totallinea = importelinea.subtract(importelinea.divide(porcentaje).multiply(dto));

            getItem().setImporte(totallinea);
        }
    }

    private void buscarprecio(BigDecimal precio) {
        Integer levelofservice;
        UUID productoid;
        BigDecimal precioproducto = BigDecimal.TEN;
        levelofservice = contratosProductosDs.getItem().getContrato().getNivelServicio().getId();
        productoid = contratosProductosDs.getItem().getProducto().getId();
        precioproducto = ProductosPreciosDs.getItem().getPrecio();
        return;
        /*Statement stmt = conn.createStatement();
        ResultSet rs = stmt.("SELECT Lname FROM Customers WHERE Snum = 2001");*/
    }

}

1 Like