Foros de discusión

Programmatic control of Announcements & Alerts portlets

Steve Hideg, modificado hace 8 años.

Programmatic control of Announcements & Alerts portlets

New Member Mensajes: 3 Fecha de incorporación: 16/12/15 Mensajes recientes
Hello,

Is there any way to programmatically control the contents and behavior of the Announcements and Alerts portlets from external systems?

I'm looking for a way to have an external system add entries to the announcements portlet and another system to control the alerts portlet based on external data and conditions without someone having to manually enter this data on the portal.

Thanks.

—Steve Hideg
thumbnail
Andrew Jardine, modificado hace 8 años.

RE: Programmatic control of Announcements & Alerts portlets

Liferay Legend Mensajes: 2416 Fecha de incorporación: 22/12/10 Mensajes recientes
Hi Steve,

I have never tried this before but I am willing to throw out an idea or two that you could try emoticon. Actually it's only really a half idea as it only addresses announcements.

Liferay ships with a REST-like service implementation for most of the services API. Assuming you are using the Tomcat bundle on 8080, on your local machine you can see the listing of the services by going to


http://localhost:8080/api/jsonws


If you enter announcements into the search field you will find that there are several options, one of which includes AnnouncementsEntry, add-entry. This might help you to acheive the first half of your question (always assuming that the external system can access the Liferay system of course).

Can you give that shot and let us know if it helps? If it does then perhaps you could do something similar for alerts using a Struts Action hook or something.
Steve Hideg, modificado hace 8 años.

RE: Programmatic control of Announcements & Alerts portlets

New Member Mensajes: 3 Fecha de incorporación: 16/12/15 Mensajes recientes
Thanks Andrew.

This looks promising, except for the fact that I have to log in through a CAS server first.
We're actually using Luminis portal 5.2.1 which sits atop Liferay 6.1.20 EE. Users have to authenticate using a CAS server.
I guess I'd have to figure out a way to bypass CAS for this.

Many of the parameters have self-explanatory names, but many don't. Do you know where I might find info on the following?

p_auth (maybe this can help getting around CAS?)
plid
classNameId
classPK
url
type
priority
alert

Thanks.

—Steve
thumbnail
Andrew Jardine, modificado hace 8 años.

RE: Programmatic control of Announcements & Alerts portlets

Liferay Legend Mensajes: 2416 Fecha de incorporación: 22/12/10 Mensajes recientes
Hi Steve,

I've never used your configuration before so I'm not entirely sure how to work around it. I can tell you that in the past though I have used curl to execute this things. In fact, I have used curl to access non jsonws urls that are secure as well. It just meant that I had to first curl the auth url with credentials and then iunclude the resulting cookie in subsequent requests to perform them as the authenticate user.

Do you think something like that might work for your setup?

As for the second part of your question, it's a little more involved. I would wait to address that part until you got past the CAS bit emoticon. For the record though the p_auth token is not a work around for login. Its a token that is generated by liferay for action requests to help prevent CSRF attacks.

Let's start with the CAS bit and get past that first. Forget Liferay for a second, can you authenticate against your CAS server using something like curl? (I know you might not use curl in your final solution, but it would allow use to determine if there was a way to get an authenticated session without going through th GUI).
Steve Hideg, modificado hace 8 años.

RE: Programmatic control of Announcements & Alerts portlets

New Member Mensajes: 3 Fecha de incorporación: 16/12/15 Mensajes recientes
Andrew,

I've done my homework and have figured out how to get to /api/jsonws (or any path, really) on our portal, authenticating to CAS along the way.

I have a perl script doing this. I'm willing to share if people want to see it.

Anyway, I guess the next step is to figure out how to actually use this API, so my questions still stand.

Many of the parameters for add-entry have self-explanatory names, but many don't. Do you know where I might find info on the following?

p_auth (maybe this can help getting around CAS?)
plid
classNameId
classPK
url
type
priority
alert

In addition to those (and perhaps included in those), is there a way to target announcements to particular audiences?

Thanks.

—Steve


Thanks.
thumbnail
Andrew Jardine, modificado hace 8 años.

RE: Programmatic control of Announcements & Alerts portlets

Liferay Legend Mensajes: 2416 Fecha de incorporación: 22/12/10 Mensajes recientes
Hi Steve,

I can try to explain some of them but I am not familiar with all of them. You may need to hopw someone else fills in the blanks or do a little digging emoticon

p_auth (maybe this can help getting around CAS?)
This is something that is generated by Liferay to help prevent CSRF attacks. It's only application for Action URLs. I believe there is a way to generate this using JS for initial calls. The documentation should cover how this works and how to use it.

plid
This is the page layout id. A "page" created in the portal is referred to as a Layout (in the API). Each layout has a unique identifier... and this is the plid. The importance of this field is that it tells the portal which "page" you want to route a request to .Imagine you have PortletX and this portlet has been added to 3 different pages. You might want to create a PORTLET request that targets PortletX, but on a specific page. The plid ensures that "page" is the one that gets the request. (incidentally, the p_p_id is the portlet is which is the portlet on the plid that would get the request).

classNameId
There is a table in the database called ClassName_. In this table you will find the id (referenced here) and the corresponding model object. This is the way that Liferay is able to use one database table for multiple types of "objects". So imagine that you have a table that stores some "generic" information related to a model. You can use the classNameId as the "model" reference -- think of it like a foreign key, though there is no FK. It's implicit.

classPK
This is a reference to the ACTUAL record. So if you have a User model object with a classNameId of 1123 ... and then 3 user records in the User table 111, 222, 333, then this column specifies that this record is in reference to, for example, user 333.

url
Not sure about this one. Perhaps it's just where you want to take the user in reference to the alert? For example, you get a notification that you have a new workflow task to approve something... perhaps this url can take you directly to the item?

type
Not sure but I would assume that it has soemthing to do with the type (duh) of notification -- for eg, Info, Warn, Error .. that kind of thing. Totally guessing though.

priority
Should be pretty self explanatory I think.. probably just how high in a list it has to appear. Maybe it has something to do with the rendering (red versus green text or soemthing?)

alert
I think this would determine whether or not it shows up in teh alerts portlet but again, I am not sure.


Best thing to do at this stage is to have a poke through the Portal's source code to see what shows up. For the views you will find them under ROOT/html/portlet ... the implementation classes should be in the portal-impl project (com.liferay.portlet.*). Liferay does a really good job (I think) of making their source coude and packaging semantic so it should be pretty easy to work through.
thumbnail
Julien Nart, modificado hace 7 años.

RE: Programmatic control of Announcements & Alerts portlets

New Member Mensajes: 12 Fecha de incorporación: 30/12/16 Mensajes recientes
Hi everyone,

I would like to add new announcements programmatically using the json api provided by the portal like explained but I don't find all the information that I need to use it.

Thanks for your description of the parameters !
I found no descriptions excepted yours for the parameters, no examples, ...

Do you know how I can get values like plid, classNameId, classPK ? (I'm still trying to get it using you description).

Thanks in advance!
thumbnail
Andrew Jardine, modificado hace 7 años.

RE: Programmatic control of Announcements & Alerts portlets

Liferay Legend Mensajes: 2416 Fecha de incorporación: 22/12/10 Mensajes recientes
Hi Julien,

In Liferay, through the admin, you can add "Pages" to your site. The "Pages" you add, in the API, are referred to as Layout objects. These objects, in turn, are stored in the Layout tables in the database. One of the attributes of the Layout object is the plid -- which is a short hand for "page layout id". When you are creating portlet requests you need to specify the portlet that you want to receive the request. Think of it this way...

I live on a street called Pape. If you want to send me a letter, you don't just send your letter to "Andrew Jardine, Pape Ave." -- you have to include my actual house number. The Portal Container is kinda like "Pape Ave" in this example and the portletId (p_p_id) is the house number, or portlet that you want to get the request.

But what does that have to do with plid? well.. this is the cool thing. If you want to send a message to a portlet that is on a page that your user is not on, you can do so by specifying the plid of the page. So if I have two pages.

Home
Dashboard

... and I know that the announcements portlet is on the Dashboard page, I can create a portlet URL and include the plid of the Dashboard page. When the portal container receives the request it will see the plid, lookup that page, find the portlet specified by the p_p_id and send the request to it. This means that I could be on any page in the site and access the functions of an announcement portlet that is somewhere else. Incidentally, if you DON'T specify the plid, then Liferay will assume that you are trying to talk to a portlet that is on your current page -- and if it is not there, nothing will happen.

ClassPK and ClassNameId is something that is used to "genericize" the data model. For example, there is a portlet called the Asset Publisher. "An asset" in Liferay can refer to many different objects. It could be a User, an Organization, a Journal Article (web content), a File Entry, .... etc. The idea is that an Asset is a general term that can be used to describe all those things and that using this generalization I can write a portlet that can display different combinations of all these assets without having to create n! portlets. It also means that as I add NEW CUSTOM ASSETS, the same OOTB portlets can be leveraged. The challenge though is how to store this information without having to create n! tables! .. enter the ClassNameId and ClassPK.

All Assets have, for example, a title. Rather than create a table with Journal Article Asset entries, and another for User Asset entries, we put them all in the AssetEntry table. But then how do we know if we are looking at a User or a Journal Article? They both have a title and while it may be obvious in some cases, there are others where you would never know. The ClassNameId is an identifier that refers to the model that the entry is related to. There is a table in the database that stores these references -- called ClassName_.

If you go to your database and run this query --

SELECT * FROM ClassName_ where value like '%Announcement%';


... you will probably find 3 entries. One of them is com.liferay.portlet.announcements.model.AnnouncementsEntry which is a reference to the Java class that models an announcement that is added to the system.

So, in the Asset table we have the generic attributes of an announcement, and then the classNameId which is a reference to the java model. The classPK is the last one in question which by now you have probably guessed is the ID of the AnnouncementEntry record (in the AnnouncementEntry table) that the AssetEntry is related to. We can call it a foreign key, but it's not really an FK because there is no enforcement of the relationship.

Now, in the case of Announcements, it's the same concept as Assets. I have different types of announcements right? so I am going to create AnnouncementEntry records and use the ClassNameId and ClassPK to store pointers that help identify the detailed TYPE of announcement and specific announcement record.

Does that make it a little clearer?
thumbnail
Julien Nart, modificado hace 7 años.

RE: Programmatic control of Announcements & Alerts portlets

New Member Mensajes: 12 Fecha de incorporación: 30/12/16 Mensajes recientes
Hi Andrew,

Thank you VERY MUCH for you good explanation and thank you for responding so quickly !!!
It's clearer now !

Can you say me if I'm right ? so:
- for the classNameId, I have to take the one of the class that models an announcement (com.liferay.portlet.announcements.model.AnnouncementsEntry)
- for the plid, I have to take the one of the page where I can find the announcements portlet (I did it by calling and displaying the value of
themeDisplay.getLayout().getPlid();
in a portlet added in the same page as the announcements portlet, but I could get it in the Layout table too I think, like you explained).

- for the classPK, because it's the ID of an AnnouncementEntry record, it will be the id of this new announcement entry, right ? So I need to check what is the latest id used by an asset and increment it ?

Many thanks for your feedback !
thumbnail
Andrew Jardine, modificado hace 7 años.

RE: Programmatic control of Announcements & Alerts portlets

Liferay Legend Mensajes: 2416 Fecha de incorporación: 22/12/10 Mensajes recientes
Hi Julien,

So I just did a quick test on my end. I added an announcement that is General scope so that it goes to everyone. With the general scope, since it is not targeted ,the classNameId and classPk are both 0 in the database. WHen I add one that is scoped to my "Site" then the classNameId corresponds to the com.liferay.portal.model.Group object (A site in the UI is mapped to a Group in the API/Database). I assume that if I added an announcement for a Role, then the classNameId on the announcement record would relate to Role object.

The plid in the theme display is the plid for the page you are on. You can use code like this to get the layout for another page

Layout layout = LayoutLocalServiceUtil.getFriendlyURLLayout(groupId, isPrivate, "/your-friendly-url")


To increment the counter, you just need to use the CounterLocalServiceUtil.increment() method.
thumbnail
Julien Nart, modificado hace 7 años.

RE: Programmatic control of Announcements & Alerts portlets

New Member Mensajes: 12 Fecha de incorporación: 30/12/16 Mensajes recientes
Hi Andrew,

Ok THANKS !

I successfully sent an alert and an announcement using the api and your latest explanations emoticon

I will try to send announcements using different scopes like mentioned (not the classNameId for the general scope like I did but with a classNameId for Groups, Roles, ...)

Thank you very much for your time and your help !

Have a nice day,
Julien
thumbnail
Julien Nart, modificado hace 7 años.

RE: Programmatic control of Announcements & Alerts portlets

New Member Mensajes: 12 Fecha de incorporación: 30/12/16 Mensajes recientes
Hello,

I successfully added entries for other roles (like User) using the api but there are not visible (visible in admin when you select the scope "User", you see the entries). (used the classnameid of a Role as classNameId value in the api and the role User as classPK value).

Also, I would like to send an alert to a specific user, so I used as classNameId the classNameId of the class com.liferay.portal.kernel.model.User (20087 in my db) and as classPK, the userId of my user (did a select in the table user_ and found the userid 32484 for example).

When I did it, it works but nothing is visible for this specific user, do you have any idea ?

Thanks,
Julien.
thumbnail
Andrew Jardine, modificado hace 7 años.

RE: Programmatic control of Announcements & Alerts portlets

Liferay Legend Mensajes: 2416 Fecha de incorporación: 22/12/10 Mensajes recientes
Hey Julien,

The easiest way to help you troubleshoot is if you are able to share your code with us. Is that possible?
thumbnail
Julien Nart, modificado hace 7 años.

RE: Programmatic control of Announcements & Alerts portlets

New Member Mensajes: 12 Fecha de incorporación: 30/12/16 Mensajes recientes
Hey Andrew,

I created user groups and I put some users into it (in Control Panel > Users > User Groups, I see the groups and my users are in it).

I wanted to send alerts to a user group and then see if a user who is logged in received it.

This is what I used for the api:

classNameId : the classnameid of the class com.liferay.portal.kernel.model.UserGroup (did a select on the table classname_ and I found the classnameid 20088)

classPK: the usergroupid of the usergroup I want to send a message to (did a select on the table usergroup and I found the usergroupid 30302)

all the other parameters are ok (it sends it to everyone by using classnameid 0 et classPK 0, for general like you explained).

But when I sign in using one of the user accounts which is in this group, I receive no alert.

I can see the alert entry using the administrator account (test@liferay.com), in the alert portlet by selecting the distribution scope UserGroups > MyUserGroup, so it worked I think but I don't see the alert in the "new" or "previous" tab of the alert portlet.

Thanks