Static attribute or singleton object shared between views

Hi.
I need to share some values that can be modified and used by many views.
I tried using static attribute and session scoped singleton bean and instantiating using AppContext listener applicationStarted().
But the change in a view is not detected by other.
Thank you.

Hi,

Could you share some code? Also, please explain, should this data belong to one user session or to all current sessions?

This specific data belong to one user session.

It’s a working date, the default value is the current date, but the user could set to a previous day.
This date will be used in whatever view the user has access. For example, as the day of the entries in the stock or financial modules, without the need of change it for every entry.

What I’m doing:

  1. Declare a simple class with static attibute: (Global module)
package br.inf.devtech.cafe.singleton;
import org.springframework.stereotype.Component;
import java.util.Date;

@Component(SingleClass.NAME)
public class SingleClass {
    public static final String NAME = "cafe_SingleClass";
    public static Date dataTrabalho;
}
  1. Initialize default value: (Core module)
package br.inf.devtech.cafe.listener;
import com.haulmont.cuba.core.sys.AppContext;
import org.springframework.stereotype.Component;

@Component("cafe_AppStart")
public class AppStart implements AppContext.Listener {
    public AppStart() {
        AppContext.addListener(this);
    }
    @Override
    public void applicationStarted() {
        SingleClass.dataTrabalho(new Date());
    }
    @Override
    public void applicationStopped() {
    }
}
  1. Change the value in one view: (Web module) Attribute can be accessed and setted in the method gravar.
package br.inf.devtech.cafe.web.screens;

import br.inf.devtech.cafe.singleton.SingleClass;
import com.haulmont.cuba.gui.components.AbstractWindow;
import com.haulmont.cuba.gui.components.DateField;
import javax.inject.Named;
import java.util.Map;

public class Screen extends AbstractWindow {
    @Named("dpDataTrabalho")
    protected DateField dpDataTrabalho;
    @Override
    public void init(Map<String, Object> params) {
        super.init(params);
        dpDataTrabalho.setValue(SingleClass.dataTrabalho);
    }
    public void gravar() {
        SingleClass.dataTrabalho = dpDataTrabalho.getValue();
    }
}
  1. Trying to use it in another view (Web module) Returns default value
    calendar.setTimeInMillis(SingleClass.dataTrabalho.getTime());

  2. Accessing the view in step 3 and the value is what was setted.

I’m using cuba framework to develop a ERP system for small brazilian coffee producers.
Thanks for your time and great framework.

Let me first explain why your approach does not work.

  1. You use a bean defined in the global module to store values. This bean will be instantiated separately for core and web modules (in different classloaders), so the value will be in different objects.

  2. Requests are handled by different execution threads, so you have to provide visibility of your variable. For example, add accessor methods and make them synchronized.

  3. The bean will share data between all user sessions, but you said you need it for current session only.

A simple solution for you would be using CUBA session attributes (UserSession - CUBA Platform. Developer’s Manual):

@Inject 
private UserSessionSource uss;

private void someMethod(Date date) {
    uss.getUserSession().setAttribute("mydate", date);
}

private void someOtherMethod() {
    Date date = uss.getUserSession().getAttribute("mydate");
}

Keep in mind, that attribute values are passed from client to middleware, but not vice versa. That is if you set a value in a screen, you will get it in other screens and in middleware beans. But if you set an attribute in a middleware bean, you will see it only on the middleware.

Worked. Thank you.:vulcan_salute: