Ask Questions and Find Answers
Important:
Ask is now read-only. You can review any existing questions and answers, but not add anything new.
But - don't panic! While ask is no more, we've replaced it with discuss - the new Liferay Discussion Forum! Read more here here or just visit the site here:
discuss.liferay.com
RE: Define a "default render" command for a MVCPortlet?
All examples for MVCPortlets show the portlet definition with a default view jsp.
However as I need to retrieve data to populate that view, I would like to do that in a (reusable) render command.
But I can't find a way to define a the render command in the portlet annotation instead of the view jsp:
But instead of referencing a .jsp page in javax.portlet.init-param.view-template, I would like to tell Liferay that it should call a specific RenderCommand when the portlet is initially displayed.
I would like to avoid putting that into the Portlet's render() method, because that would duplicate the code between the RenderCommand and the render() method.
How can I do that?
However as I need to retrieve data to populate that view, I would like to do that in a (reusable) render command.
But I can't find a way to define a the render command in the portlet annotation instead of the view jsp:
@Component(
immediate = true,
property = {
"com.liferay.portlet.display-category=MyPortlets",
"com.liferay.portlet.instanceable=false",
"javax.portlet.display-name=Display Portlet",
"javax.portlet.init-param.view-template=/myportlet/list_data.jsp",
"javax.portlet.name=my_portlet",
"com.liferay.portlet.ajaxable=false",
},
service = Portlet.class
)But instead of referencing a .jsp page in javax.portlet.init-param.view-template, I would like to tell Liferay that it should call a specific RenderCommand when the portlet is initially displayed.
I would like to avoid putting that into the Portlet's render() method, because that would duplicate the code between the RenderCommand and the render() method.
How can I do that?
My workaround for now is the following hack in the render() method of the portlet:
public class MyDisplayPortlet
extends MVCPortlet {
private final DisplayCommand displayData = new DisplayCommand();
@Override
public void render(RenderRequest renderRequest, RenderResponse renderResponse)
throws IOException, PortletException {
String renderCmd = ParamUtil.getString(renderRequest, "mvcRenderCommandName", null);
if (renderCmd == null) {
String mvcPath = displayData.render(renderRequest, renderResponse);
renderRequest.setAttribute(getMVCPathAttributeName(renderResponse.getNamespace()), mvcPath);
}
super.render(renderRequest, renderResponse);
}
}Creating an additional instance of the render command feels like a hack though.
Thomas Kellerer:
Creating an additional instance of the render command feels like a hack though.
It probably also won't work if your DisplayCommand needed to have any of its references satisfied by OSGi, since you're essentially instantiating the object yourself instead of letting OSGi do it for you.
An alternate option is to use the MVCCommandCache to grab the existing object during the render phase, if it hasn't already been set. That allows you to take advantage of Liferay storing the references.
@Override
public void render(RenderRequest renderRequest, RenderResponse renderResponse)
throws IOException, PortletException {
if (displayData == null) {
displayData = getRenderMVCCommandCache().getMVCCommand("def");
}
// ...
}Another option is to use @Reference to get the existing component instantiated/managed by OSGi. This allows you to take advantage of OSGi storing the references.
@Reference(target="(&(javax.portlet.name=abc)(mvc.command.name=def))")
private MVCRenderCommand displayData;
Thanks for the answer.
There is no method getRenderMVCCommandCache() in MVCPortlet and access to the instance variable _mvcRenderCommandCache is private.
So I don't see how I could use that cache.
But, using the @Reference annotation seems to work.
There is no method getRenderMVCCommandCache() in MVCPortlet and access to the instance variable _mvcRenderCommandCache is private.
So I don't see how I could use that cache.
But, using the @Reference annotation seems to work.
Thomas Kellerer:
There is no method getRenderMVCCommandCache() in MVCPortlet and access to the instance variable _mvcRenderCommandCache is private. So I don't see how I could use that cache.
Whether that method is available depends on the version of com.liferay.portal.kernel you are compiling against, and to some extent which version of Liferay you are running.
Based on the blame on the file, the method wasn't added until LPS-68922, which has a DE-8 label. It also has a fix version of 7.0.3 GA4, so if you're running 7.0.2 GA3 or earlier or you built from source before DE-8, the method really isn't available.
If you're using one of the later releases, checking the releases between DE-7 (2.12.x) and DE-8 (2.16.x), the earliest version of com.liferay.portal.kernel that provides that method is 2.13.0, so if your dependency version is anything lower than that (it's typical to have a dependency version that is 2.0.0 or 2.6.0 if you follow Liferay examples), the compiler would be unable to find it.
Adrian Rodriguez Monedero, modified 6 Years ago.
New Member
Posts: 15
Join Date: 10/17/10
Recent Posts
After checking the source code of MVCPortlet in Liferay 7.0, it seems as you could define a default render command declaring this component property of your display command:
"mvc.command.name=/"
Just as a note: using "mvc.command.name=/" will work to render a MVC command, however, there are two issues with this method:
The first one is that is an inconsistent behavior in the portal side,
one cannot put any command there, just the one called "/".
The second one is that will break other portlet modes, like edit.