RE: Make Custom Entity Asset

Dorian Penot, modified 6 Years ago. Junior Member Posts: 25 Join Date: 3/14/19 Recent Posts
Hey everyone ! i m there again to ask your help ^^ I m tryin to make my customs entities as Assets. I followed this https://portal.liferay.dev/docs/7-0/tutorials/-/knowledge_base/t/adding-updating-and-deleting-assets-for-custom-entities to add a line in the AssetEntry table. This is working fine.I rode about a render for my Custom Entity but i saw that it's rendering the title and description if u don't do any render, and this is enough. I found it here at the third line :https://portal.liferay.dev/docs/7-0/tutorials/-/knowledge_base/t/rendering-an-asset
My problem is that the line is added in asset but it's not displaying and not searcheable, what did i do wrong ? 
thumbnail
Mohammed yasin, modified 6 Years ago. Liferay Master Posts: 593 Join Date: 8/8/14 Recent Posts
Hi,
 You need to index custom entity and make it available for search portlet by implementing opensearch
Please refer below .
https://liferay.dev/forums/-/message_boards/message/84418151
1. Indexing Custom Entity Refer 
https://portal.liferay.dev/docs/7-0/tutorials/-/knowledge_base/t/creating-a-guestbook-indexer
2. For making custom enitity available in search portlet you need to implement opensearch 
https://github.com/liferay/liferay-portal/blob/7.0.x/modules/apps/web-experience/journal/journal-service/src/main/java/com/liferay/journal/search/JournalOpenSearchImpl.java
thumbnail
Andrew Jardine, modified 6 Years ago. Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
Hey Mohammed, Just a small correction. You don't need to implement the OpenSearch interface to make your entity searchable with the Liferay search -- all you have to do is make sure that your search configuration includes the model for your custom entity.  If you have implemented the indexer, then they will be found, and if you have implemented the Asset Renderer, then they will be rendered as part of the out of the box functionality. Open Search is for something else altogether. Implementing this interface allows you to use a global search bar (read: browser) and set the scope of the search to the current site -- so you search the "Liferay site" but using your browser in place of the search portlet. Normally you have to actually make configuration changes to your browser to enable this behaviour. Outside of this correction, I would agree with everything else you've said here -- custom indexer, custom renderer and I would also add several methods to my service definition (MyCustomEntityLocalServiceImpl) that you can use to invoke searches.
Dorian Penot, modified 6 Years ago. Junior Member Posts: 25 Join Date: 3/14/19 Recent Posts
I followed the second link creating the same but it didn't work ... I don't understand because when i create one it appear in the database in asset table, it's also indexing properly and searchable throw ElasticSearch but not in the liferay search portlet.
I can also select my entity in asset publisher portlet configuration, but they don't appear in the portlet .. I have no error 
Dorian Penot, modified 6 Years ago. Junior Member Posts: 25 Join Date: 3/14/19 Recent Posts
Okay after fex days of deep torture, i finally succed to make my asset searchable by adding this in my indexer : 
        document.add(new Field(Field.GROUP_ID,Long.toString(ENTITY.getGroupId())));
        document.add(new Field(Field.SCOPE_GROUP_ID,Long.toString(ENTITY.getGroupId())));
        document.add(new Field(Field.STATUS,Long.toString(0L))); 
But my torture is not finish, now in he search result i have 0 result displaying but i can see 4 documents and 1 of my entity in the type tab on the left. I don't undertand, i tried to edit the getJspPath() method and i added a full_content.jsp file in my service builder Meta-in/ressources/asset/entityName folder. Nothing changed. If my result contain one of my custom asset the rendering dont work ... Helppppppp
thumbnail
Mohammed Yasin, modified 6 Years ago. Liferay Master Posts: 593 Join Date: 8/8/14 Recent Posts
Check  whether your asset renderer is getting called by adding log in your gettitle() or getjsppath ()  or any exception your getting  while rendering your custom asset
thumbnail
Mohammed Yasin, modified 6 Years ago. Liferay Master Posts: 593 Join Date: 8/8/14 Recent Posts
Also check have u added Field.CLASS_NAME_ID,and Field.CLASS_NAME_ID to your  document.add();
Dorian Penot, modified 6 Years ago. Junior Member Posts: 25 Join Date: 3/14/19 Recent Posts
That's my biggest problem ... I don't have any logs even if i put some in the fonctions. The only logs appearing is when i deploy in the assetrendererfactory in the constructor method. I also don't have any error  warning or exception. What do you mean by Field.CLASS_NAME_ID ? 
thumbnail
Mohammed Yasin, modified 6 Years ago. Liferay Master Posts: 593 Join Date: 8/8/14 Recent Posts
thumbnail
Andrew Jardine, modified 6 Years ago. Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
Let's shed a little light for you on CLASS_NAME and CLASS_NAME_ID and CLASS_PK. This is an important pattern in Liferay to understand as you work with the product because it is used extensively, and once you get a handle on it, it allows you to start wiring in a lot of the out of the box features into your custom features. 

First things first, since you have a service builder project and you have generated some custom entities, go to your database and do a SELECT * on the ClassName_ table.

You'll find many familiar references in here, along with the custom stuff that you have added. So basically, when you use Service Builder to generate your entity and deploy your module, one of the many things that happens is you get an entry in this table. So what is it used for?

Truthfully, I have always struggled to explain this -- I understand it, just finding the right words seems to be a challenge. The best way I have come up with to date is that the ClassName, ClassNameId and ClassPK are ways to "genericize" references. The AssetEntry is a great example, but there are many more -- Ratings, Subscriptions, etc. The challenge is, how do you data model something like a Rating (which is generic) but then associate it to something specific, like a Message Board Post vs. a Blog Post. Well, in Liferay, we do this with the ClassName, ClassNameId, ClassPK stuff.I'm just going to make numbers up here to illustrate the point. Let's say in your ClassName_ table you have the following.

Class Name                                              Class Name Id
com.liferay...JournalArticle                                 21005
com.liferay...BlogEntry                                      22004
com.abc...Player                                             24500

Where the first two rows are of course out of the box entries, and the last one is a reference to your custom entity. Let's assume that you have a Player table with the following --

Player ID      Name                  Position      Age       Retired
21345          John Snow                CF          22        False
98432          Chris Jade               RD          20        False

Now, if you use the Liferay pattern then that means you can identify John Snow, as

className=com.abc...Player
classNameId=24500classPK=21345

... so in your code you can identify the model and the specific data record by combining the class name and the PK from the player table. So, if you wrote a portlet that rendered player details for example, and then you added the option to be able to "rate a player" you don't have to write all that plumbing to manage ratings yourself. You can use Liferay's Ratings API and services to record ratings for Player, John Snow, in the Ratings tables and then you can use the Ratings taglibs to render them in your portlet. AND! like I mentioned above, this pattern can repeat itself for other features like comments, subscriptions, asset entries etc.  So it's a way to genericize meta data about your entity but store it in a central table so that you don't end up with a Ratings_Blogs table and a Ratings_Journal_Article table and a Ratings_Player table etc. 
Make sense?
Dorian Penot, modified 6 Years ago. Junior Member Posts: 25 Join Date: 3/14/19 Recent Posts
Sorry for the very late answer but i ve been making my brain over work on that problem ... ;)

So yes it definitly make sense ! but i guess that's not what i meaned in my question (My english is surely bad i m French emoticon ), i have the entity in asset Entry and my search portlet is finding it. Let me explain you : 

Let's take an Ads entity. I create my ad throx my portlet, my elasticsearc hindex it correctly and the assetEntity Table is updated. Until there everything look fine. But when i instanciate an AssetPublisher portlet, i can't see my entity, so i decided to filter in the configuration. I seletco only my custom Ads entity (yes it appear in the configuration).I got a "No values found" in the AssetPublisher Portlet. 

You wil lsay, "Your entity is just not indexed correctly or not seted up as an asset follow the docs" wich would be totaly correct. But there it start to get weird. If i write the name of my Ads i just created in  the global search, i will see Ads (1) in the Typpe select on the right, and other normal searchable Stuffs, but still thet "No Values found" in the result. 

I have no error, i have setted up a render and rendereFactory for my both entities. I also created a JSP, i trieds to follow the old 6.2 tutorial too with the EntityAsset working with my custo mentity asset. Nothing is working ! To be honest i can't find any clue of where is the rerror coming from ... 
thumbnail
Andrew Jardine, modified 6 Years ago. Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
Hi Dorian,

I speak French, so you could try to explain it in French if you think that will help. I will warn you though that I don't get to use my French very much these days so my replies might be a little bit like your English. Maybe you can write to me in French and I can write to you in English haha emoticon

Ok -- it certainly sounds like everything you have is correct. I mean, the AssetFactory, the Renderer and the fact that you have a facet in your search rights showing up with a count for your type means that if much be found. You're referencing the 7.0 Documentation .. so I just want to clarify something. You are dusing a Liferay 7.0 installation, but can you clarify specifically which version?

The next thing I would try would be to remove the search portlet from the equation and try with a custom query. If you create a new MVC Portlet, then in the render method you can try to use something like this --
long companyId = _portal.getCompanyId(portletRequest);
long groupId = _portal.getScopeGroupId(portletRequest);

// build the basic object

HttpServletRequest request = _portal.getHttpServletRequest(portletRequest);
HttpServletRequest originalRequest = _portal.getOriginalServletRequest(request);

SearchContext searchContext = SearchContextFactory.getInstance(request);
searchContext.setEntryClassNames(new String[]{Ads.class.getName()});
searchContext.setStart(0);
searchContext.setEnd(10);

Indexer indexer = IndexerRegistryUtil.nullSafeIndexer(Ads.class.getName());
Hits hits = indexer.search(searchContext);

Or something close to that -- I'm going a bit from memory here. If you then set a breakpoint after the last line above, then you you can inspect the Hits and the SearchContext objects to understand what is being passed to elastic. Just make sure, in your portlet class, to inject a service for the Portal .. or change the references above (_portal) to use PortalUtil instead.

@Reference
private Portal _portal;
.. also, are you able to share the code for your indexer class with us?
Dorian Penot, modified 6 Years ago. Junior Member Posts: 25 Join Date: 3/14/19 Recent Posts
Hey thanks for your answer !

I m running on Liferay CE 7.1.1-ga2, using a Service Builder and React portlets. I will try what you said, I add my indexer as attachment.
thumbnail
Andrew Jardine, modified 6 Years ago. Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
Great -- and just one more clarification. Starting in 7.1, there were actually two different search portlet options. There was the "legacy one" for lack of a better name which, whne added to a page, was one portlet that had the results, the facets, etc. There is also a "new set of search portlets" that allows you to add individual facets, results, search bar, etc.

I am assuming you are using the new one, but just wanted to double check. Is my assumption correct?

EDIT: Another question. You mentioned that you created the Asset Renderer for this custom entity as well right? When you add an AssetPublisher widget to a page and configure it to show your custom asset, do the entries show up?
Dorian Penot, modified 6 Years ago. Junior Member Posts: 25 Join Date: 3/14/19 Recent Posts
I m using the default one, i will show u a screenshot of what i get
thumbnail
Andrew Jardine, modified 6 Years ago. Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
Ok, yeah, that is the new one. That's good to know -- makes testing a little more relevant (since I can make sure to try with the same one haha).

What about the asset publisher? Does it render your custom items? I ask because I have seen occasion in the past where the search was actually returning items (hence the facet count you are seeing) BUT, the Asset Renderer was not working and so the result was not rendering.
Dorian Penot, modified 6 Years ago. Junior Member Posts: 25 Join Date: 3/14/19 Recent Posts
In the asset Publisher I can select the PetitesAnnonces entity, but i can't see any item in the portlet. Attachments again ^^ On the assetPublisher portlet you can see the portlet on the right with two entities, and the asset on the left.
thumbnail
Andrew Jardine, modified 6 Years ago. Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
Ok, in that case I would focus my attention on the asset renderer. Two questions.

1. Are there any errors in the log? (I do recall having this issue and I think it was silently gobbled up, but I can't say for sure)

2. If you set a breakpoint in your asset renderer.. does it hit?
Dorian Penot, modified 6 Years ago. Junior Member Posts: 25 Join Date: 3/14/19 Recent Posts
I think that's where it's coming from. I will send u my two renderer class. Unfortunatly i have no error ! on the asset publisher portlet and on the search portlet no error. The renderer breakpoints don't hit either, the constructor only hit when i start my serveur.
thumbnail
Andrew Jardine, modified 6 Years ago. Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
Alright, progress! emoticon

I wish I could remember what I did to solve this problem when I had it, but it was about a year and a half ago and I can barely remember what I had for dinner last night, sooooo. I'm going to check with a former coworker of mine shortly to see if she remembers what it was. In the mean time can you do the usual stuff of checking to make sure you factory service is resolved and active in the Gogo shell?

scr:info agiir.bd.serviceBuilder.assets.PetitesAnnoncesAssetRendererFactory

.. it's probably fine, but just to eliminate another possibility. And one more thing to try while you are waiting for me to ask my former co-worker, can you change the getJspPath method implementation in the asset renderer class to use

public String getJspPath(HttpServletRequest request, String template)
{
return "/asset/summary.jsp";
}

which I believe will use the "summary.jsp" from the asset renderer portlet that Liferay ships with.
Dorian Penot, modified 6 Years ago. Junior Member Posts: 25 Join Date: 3/14/19 Recent Posts
Well i tried what you said me and ... Still the same stuff ^^ It's terribly frustrating, when i do scr:info i got my AssetRendererFactory detected as active and working fine. I trie to do some fix i found on other topic in that forum but it's having no effects ! 
thumbnail
Andrew Jardine, modified 6 Years ago. Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
Hey Dorian,

I get it -- and we have all been there I'm sure, and not just with Liferay of course. I am sure that we can find an answer and I am equally sure that when we do find the answer it will be an "OMG! Are  you kidding me?!" moment emoticon

Ok, last resort, if you are willing to package up the code in a zip and share it with me, then I am happy to build and deploy on my side to troubleshoot a little more effectively. If you don't really want to attach the source here to the message thread (which I understand) maybe you can ping me on slack and we can troubleshoot there -- and report back here when we find the answer.
Dorian Penot, modified 6 Years ago. Junior Member Posts: 25 Join Date: 3/14/19 Recent Posts
Sorry for the late answer. We finally used the indexer directly in the jsp without using Assets. We had to finish it fast ^^ Thanks for your help anyway ! 
thumbnail
Andrew Jardine, modified 6 Years ago. Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
EW. .. just kidding emoticon. I get it, sometimes you have to do what you have to do to get it done and keep the wolves at bay. With that said, if you have a have a technical debt backlog item for this and want to continue to troubleshoot to figure out what the missing piece was, so that one day you can swap out the temporary fix for the better solution, I'm happy to continue to troubleshoot it with you.