掲示板

Load properties from DB to be used globally in all portlets

8年前 に Mansi Mistry によって更新されました。

Load properties from DB to be used globally in all portlets

Junior Member 投稿: 31 参加年月日: 14/09/30 最新の投稿
Hi,

We have our configuration properties name value pair stored in a database table. We need to fetch this data only once from the database(on init probably). We have created an entity in Service Builder and have finder method to get the properties. So we have a service which gives us all the configuration from database.

Now, the problem is we need to use this configuration across the portal in multiple portlets. The configuration will be in a Map as key-value pairs.

What would be the best way to achieve this?
thumbnail
8年前 に Andew Jardine によって更新されました。

RE: Load properties from DB to be used globally in all portlets

Liferay Legend 投稿: 2416 参加年月日: 10/12/22 最新の投稿
Hi Mansi,

Liferay has a class called the PrefsPropsUtil class. One of the things you can do with this class is lookup properties with scope. For example, you can scope a property to a company (Portal Instance). When you store a preference using this approach, the preference key/value pair is stored in the PortalPreferences table (where the ownerId column is the companyId).

Let's say in my portal-ext.properties file I add a property --

this.is.my.property=Some Value


.. when the portal starts it will load this property into its map. I can access it using the PropsUtil class, OR the PrefsPropsUtil class (if you don't specify a companyId it will use the default company). Stay with me I'm almost at your requirement emoticon ... Behind the scenes, the PrefsPropsUtil will first check that PortalPreferences table and if the property is found with a matching key, it is returned. If not, then the properties map is checked.

Now, in your case you basically want to do the same thing, but with your service builder based properties. I think there are a few options.

1. Omit the service builder solution and just let the properties that are saved be added to the PortalPreferences table. Assuming you don't need a property across multiple portal instances. There is a plugin in the marketplace already for this by the way: https://www.liferay.com/marketplace/-/mp/application/40141004

2. If you want to stick with your service builder stuff, then another option might be to introduct a scheduled job as part of the portlet, or a startup action, or both that will synchronize your service builder stuff with the PortalPreferences. Thsi way you can use your portlet to add your key-value-pairs, but then leverage Liferay's API and use the PrefsPropsUtil to retrieve them.

Personally I would go with #1 .. minimize your own maintenance, and use the wheels that are already rolling.
8年前 に Mansi Mistry によって更新されました。

RE: Load properties from DB to be used globally in all portlets

Junior Member 投稿: 31 参加年月日: 14/09/30 最新の投稿
Thanks Andrew for a prompt response.

The problem I see with the solution you suggested is duplication of properties. So two tables have the properties stored 1) our custom table and 2) the portalpreferences table. We would want to avoid this duplication. Is there a way we could achieve it?

We cannot really remove our table since we share our database tables across components(the two separate components being liferay portal and java component - code which is basically services).
thumbnail
8年前 に David H Nebinger によって更新されました。

RE: Load properties from DB to be used globally in all portlets

Liferay Legend 投稿: 14919 参加年月日: 06/09/02 最新の投稿
Mansi Mistry:
What would be the best way to achieve this?


Use a lazy retrieve method in your XxxLocalServiceImpl that returns a Map. Declare a private Map member value and specify it is null. In the body of the method, if the Map is null pull the values from the database to create and populate the map otherwise just return the map.

Share the service jar and all of your portlets will end up using the same Map instance.

You could even get fancy by including an "expiration timestamp" on the Map if some other process is updating the DB.

In a cluster you'll have to figure out how to handle refreshing all of the Maps if an update occurs on one node of the cluster.

Override add/update/delete methods to get rid of your internal Map instance on changes or manage the Map on your own.

Or frankly you can forget all of this nonsense. Expose a getProperty() method that takes the key and returns the value and always pulls from the database. Liferay will cache the values so it's not going to be as DB intensive as you think, Liferay will handle the cluster updates, ...
thumbnail
8年前 に Jack Bakker によって更新されました。

RE: Load properties from DB to be used globally in all portlets

Liferay Master 投稿: 978 参加年月日: 10/01/03 最新の投稿
Aside from portal properties/preferences and portlet preferences, I almost always also involve a 2nd database table called 'global' what has a 'name' column and a 'value' column. I then just use GlobalLocalServiceUtil.getValue(String name). I take this approach for many convenient reasons including : so I can quickly set a feature into 'debug' mode, set a debugTo email address for say a contact form, and so on, without needing to restart a dev, staging, or prod container.