ServiceBean in Entity

I have a UtilityServiceBean that I use for common task throughout my app. I have found myself needing to use that UtilityServiceBean in my entity. I do know that I cannot inject it, so I rather declared it as private UtilityServiceBean util; and then in a @PostConstruct init method, I instantiate the Bean using AppBeans.get().

But, I get this exception: java.lang.IllegalArgumentException: Property 'util' not found in deiproductconfig2$MyEntity. I tried adding @Transient to the declaration but then it causes a NullPointerException when trying to use the bean in the entity.

So what is the proper way to do this?

v6.10

Hi,
The proper way to obtain Spring beans in non-Spring context which does not support injection (entities, CUBA actions, tests, UI components etc) is to use AppBeans.get() every time you need to get this bean.

AppBeans.get() is very fast for singleton beans, there is no need to cache returned bean instance.

Regards,

2 Likes

So you’re saying to just not bother instantiating a bean to be used by the whole entity. Seems fair. But, to humor me a bit, is there any way to do this as described? To have one instance for the whole entity?

Perhaps not necessarily a bean. Suppose I have a master/detail composition where the detail has an association to a “status” table with several possibilities, one of which is “OK”. I want to create a MetaProperty getter getNumOk() that counts the number of “OK” details for that instance of master where I can loop through the details, checking if the details status equals the “OK” status, and incrementing the result if so. And I want to just be able to call if(detail.getStatus().equals(knownInstanceOfOKStatus)). I could get that knownInstance every time I call getNumOk but in my mind it would be more economical to find it once at init and reusing the instance

It is a bit of a contrived example but it’s an example of a field that isn’t intended to be an attribute of the entity but is just there as a reference to check against.

I hope that makes sense.

Hi,

So you’re saying to just not bother instantiating a bean to be used by the whole entity

AppBeans.get() is not instantiation. This is just obtaining previously created singleton object from Map by name.

is there any way to do this as described? To have one instance for the whole entity?

Generally you should not store any data in Entities’ attributes, other than persistent or non-persistent attributes. Because Entities are data transfer objects, they travel from middleware to UI (portal) layer and back. Their role is just to represent data model of your system.

I could get that knownInstance every time I call getNumOk but in my mind it would be more economical to find it once at init and reusing the instance

There is no single solution for the task you’ve described (caching of knownInstanceOfOKStatus instance for performance purposes).
One might turn on SQL query caching and Entity caching features to reduce unnecessary workload on database.
In other situation, if you want to re-use some data inside one screen - you might load necessary data when screen is opened, and pass this data to code which needs it.
In 3rd situation you might leave unoptimized and inefficient code as is. Because practically that particular place in code does not lead to noticeable performance problems.

1 Like

Alright. I think I’m satisfied with the answer here. I wasn’t aware that Beans existed as singletons. Knowing this, I am much more at ease with having to call AppBeans.get() everywhere.