Liferay Action Hook: how to specify a tiles redirect? - liferay

I create a Liferay 6.2 hook by following official documentation, and everything works fine.
Now I need that, in the render phase and under several conditions, my user will be redirect to a specific tiles.
Original Liferay render method says:
return actionMapping.findForward("portlet.journal.error");
By the way in my class (extending BaseStrutsPortletAction) the render method can't access to any actionMapping instance.
So... how can I obtain the same behaviour in my class?
My code says:
#Override
public String render(
StrutsPortletAction originalStrutsPortletAction,
PortletConfig portletConfig, RenderRequest renderRequest,
RenderResponse renderResponse)
throws Exception {
Boolean myCondition = .......;
if (myCondition) {
// WHAT SHOULD I DO HERE?
//return actionMapping.findForward("portlet.journal.error");
}
return originalStrutsPortletAction.render(
null, portletConfig, renderRequest, renderResponse);
}
Thank you

All you need is to return the forward name.
Instead of actionMapping.findForward("portlet.journal.error"), return just "portlet.journal.error".
BaseStrutsPortletAction#render method is called from com.liferay.portal.struts.PortletActionAdapter#render, which uses the result to call actionMapping.findForward(...).

Related

Liferay Service for Business Logics

I want to clear one doubt. I am creating my own service class to manipulate data. Should i create this service instance at class level(in MVCPortlet) or create new instance in my processAction/doView method.
Is there is any issue of thread safety while using instance level.
Fg:
public class MvcCycle extends MVCPortlet {
int counter;
LdapService ldapservice;
#Override
public void init() throws PortletException {
counter=0;
ldapservice = new LdapService(); // Option 1
super.init();
}
#Override
public void doView(RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException {
// TODO Auto-generated method stub
System.out.println("Counter hits "+ ++counter);
//
LdapService ldapservice = new LdapService(); // Option 2
ldapservice.authUser(request.getParameter("email"));
// -- some code--
super.doView(renderRequest, renderResponse);
}
#Override
public void destroy() {
System.out.println("Last counter "+counter);
counter=0;
super.destroy();
}
}
class LdapService{
public boolean authUser(String email){
if(//logic to authenticate user){
return true;
}else{
return false;
}
}
}
Here, my ldapservice initiate only once. So when multiple hits come. which code is beneficial on this time either Option1 or Option 2.
Hope i have cleared my problem.
Following up on your comment: in general: it depends. We don't have enough information to give you blank architectural recommendations.
In the context of Liferay it could make sense to utilize service builder, even if you don't have database interaction. Just create an empty entity, you'll have a service with no persistence.
<entity name="MyService" local="true"/>
That's it. Now implement MyServiceLocalServiceImpl added you're done
Edit, after your clarification: it doesn't make a difference. I'd still recommend to not instantiate at all in your portlet, because that makes your portlet dependent on the service implementation. E.g. I still go with service builder.
You're also asking about thread safety and that depends on your implementation as well. Your sample code is thread safe, but the actual code might not be. Your judgement.

Customize CreateAccountAction in Liferay Portal

I'm trying to add "User Group" Selection field while creating a user (Self User Registration form - create_account.jsp).
Here Custom fields is not helpful because Usergroup is already exists in db. I want to insert into existing Users_UserGroups table.
I'm using below hook:
But User is not added in the group and no exception is printed.
Please suggest me for any other way to achieve this.
public class CustomCreateAccountAction extends BaseStrutsPortletAction
{
public void processAction(StrutsPortletAction originalStrutsPortletAction, PortletConfig portletConfig, ActionRequest actionRequest, ActionResponse actionResponse)
throws Exception
{
System.out.println("My Custom Process Action Method is Called");
String emailid=ParamUtil.getString(actionRequest, "emailAddress");
long[] userGroupIds = null;
originalStrutsPortletAction.processAction(originalStrutsPortletAction, portletConfig, actionRequest,actionResponse);
System.out.println("This is after user is registered");
if (SessionErrors.isEmpty(actionRequest))
{
ThemeDisplay themeDisplay =(ThemeDisplay)actionRequest.getAttribute(WebKeys.THEME_DISPLAY);
long newlyCreatedUserId=UserLocalServiceUtil.getUserIdByEmailAddress(themeDisplay.getCompanyId(), emailid);
long userIds[]={newlyCreatedUserId};
long dummygroupid=16206;
System.out.println("TEST UserID="+newlyCreatedUserId);
System.out.println("TEST GroupID="+dummygroupid);
//Everything went well until here.
UserServiceUtil.addUserGroupUsers(dummygroupid, userIds);
//below sysout is not printed. and no exception or user in group db created.
System.out.println("user added to group");
}
}
public String render(StrutsPortletAction originalStrutsPortletAction, PortletConfig portletConfig, RenderRequest renderRequest, RenderResponse renderResponse) throws Exception
{
System.out.println("My Custom Render Method is Called");
return originalStrutsPortletAction.render(null, portletConfig, renderRequest, renderResponse);
}
}
for more info please have a look at this thread.
Using UserLocalServiceUtil instead of UserServiceUtil worked. Basically, the difference is that *ServiceUtil checks permissions and *LocalServiceUtil does not.
I'm not sure this is the best idea, but you can use the hook for both modify the user creación jsp and save the value via model listener on user create/modify.
Regsrds

Liferay Hook - Manipulation request parameters

I ran into a little problem with a hook. Szenario:
The Hook should override struts action /document_library/edit_file_entry which is called, whenever a user uploads a document into the document library.
The goal is to check the title of the document and rename it following a given naming-scheme.
My solution:
#Override
public void processAction(
StrutsPortletAction originalStrutsPortletAction,
PortletConfig portletConfig, ActionRequest actionRequest,
ActionResponse actionResponse)
throws Exception {
//Get old title - set new title
String oldTitle = ParamUtil.getString(actionRequest, "title");
String newTitle = "Test";
//wrap request to set param
DynamicActionRequest actionRequestNew = new DynamicActionRequest(actionRequest);
actionRequestNew.setParameter("title", newTitle );
//call original struts action with modified title
originalStrutsPortletAction.processAction(originalStrutsPortletAction, portletConfig, actionRequestNew, actionResponse);
}
The Problem is that the original Struts action in portal-impl/src/com/liferay/portlet/documentlibrary/action/EditFileEntryAction.java uses PortalUtil.getUploadPortletRequest(actionRequest); which expects a PortletRequestImpl.
But DynamicActionRequest cannot be cast to PortletRequestImpl.
See:
12:07:04,466 ERROR [http-bio-8082-exec-44][render_portlet_jsp:154] java.lang.ClassCastException: com.liferay.portal.kernel.portlet.DynamicActionRequest cannot be cast to com.liferay.portlet.PortletRequestImpl
at com.liferay.portal.util.PortalImpl.getUploadPortletRequest(PortalImpl.java:4067)
at com.liferay.portal.util.PortalUtil.getUploadPortletRequest(PortalUtil.java:1253)
at com.liferay.portlet.documentlibrary.action.EditFileEntryAction.updateFileEntry(EditFileEntryAction.java:653)
at com.liferay.portlet.documentlibrary.action.EditFileEntryAction.processAction(EditFileEntryAction.java:129)
at com.liferay.portal.struts.StrutsPortletActionAdapter.processAction(StrutsPortletActionAdapter.java:51)
at com.liferay.portal.kernel.struts.BaseStrutsPortletAction.processAction(BaseStrutsPortletAction.java:42)
at com.foo.hook.portlet.sites.action.MyEditFileEntryAction.processAction(MyEditFileEntryAction.java:83)
at com.liferay.portal.kernel.bean.ClassLoaderBeanHandler.invoke(ClassLoaderBeanHandler.java:67)
at com.liferay.portal.struts.PortletActionAdapter.processAction(PortletActionAdapter.java:55)
at com.liferay.portal.struts.PortletRequestProcessor.process(PortletRequestProcessor.java:169)
at com.liferay.portlet.StrutsPortlet.processAction(StrutsPortlet.java:212)
at com.liferay.portlet.FilterChainImpl.doFilter(FilterChainImpl.java:70)
at com.liferay.portal.kernel.portlet.PortletFilterUtil.doFilter(PortletFilterUtil.java:48)
at com.liferay.portlet.InvokerPortletImpl.invoke(InvokerPortletImpl.java:548)
at com.liferay.portlet.InvokerPortletImpl.invokeAction(InvokerPortletImpl.java:579)
at com.liferay.portlet.InvokerPortletImpl.processAction(InvokerPortletImpl.java:294)
at com.liferay.portal.action.LayoutAction.processPortletRequest(LayoutAction.java:944)
at com.liferay.portal.action.LayoutAction.processLayout(LayoutAction.java:688)
at com.liferay.portal.action.LayoutAction.execute(LayoutAction.java:249)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:431)
How can I change the parameter without using DynmicActionRequest? Any suggestions?
I'm running Liferay-Portal 6.1.20 EE.
Thanks in advance.
There are two approaches I can think of.
1) Create ActionRequestWrapper object and add a parameter. This would probably solve your issue.
2) Create a subclass of LR's action class. In that make the needed code changes. Create a hook and make the new action class available to LR.
I hope this helps.
You can set the parameter in existing actionRequest:
actionRequest.setParameter("title", newTitle);
It will updated with new value.

How to get portlet context in config (Liferay)?

I'd like to access the Context of the portlet in config mod (in my implement of ConfigurationAction interface).
I try since hours to get the same Context in my ConfigurationActionImpl.processAction(PortletConfig portletConfig, ActionRequest actionRequest, ActionResponse actionResponse) as I have in my doView(RenderRequest renderRequest, RenderResponse renderResponse), but without any good result.
In my doView(), I can access my portlet Context using getPortletContext() (same as getPortletConfig().getPortletContext()) and renderRequest.getPortletSession() (it's NOT the same Context instances), but I don't know how I can access one of those objects from my processAction().
Can somebody help me, please ?
This is the method I ended up using:
PortletBag portletBag = PortletBagPool.get(portletId);
DispatcherPortlet portlet = (DispatcherPortlet)portletBag.getPortletInstance();
PortletContext pCtx = portlet.getPortletContext();
In case you want to compute the portletId, you can do this:
String portletResource = ParamUtil.getString(renderRequest, "portletResource");
String portletId;
if (portletResource.contains("_INSTANCE")) {
portletId = portletResource.substring(0, portletResource.indexOf("_INSTANCE"));
} else {
portletId = portletResource;
}
As a side note, I want to mention that I needed it in order to be able to get the Spring ApplicationContext of the portlet, which I did with this:
PortletContext pCtx = portlet.getPortletContext();
ApplicationContext portletAppContext = (ApplicationContext)pCtx.getAttribute(FrameworkPortlet.PORTLET_CONTEXT_PREFIX + portlet.getPortletName());

Liferay 5.2.3 portlet configuration page issue

I wrote a portlet that has custom conf page here is configuration-action-class:
public class ConfigurationActionImpl implements ConfigurationAction {
private static Logger log = Logger.getLogger(ConfigurationActionImpl.class);
private config conf=config.getInstance();
public String render(PortletConfig config, RenderRequest renderRequest, RenderResponse renderResponse) throws Exception {
if(renderRequest.isUserInRole("administrator")){
log.info("UserRole:::admin");
return "/config.jsp";
}else if(renderRequest.isUserInRole("guest")){
log.info("UserRole:::guest");
}else if(renderRequest.isUserInRole("power-user")){
log.info("UserRole:::power-user");
return "/config.jsp";
}else if(renderRequest.isUserInRole("user")){
log.info("UserRole:::user");
}else{
log.info("UserRole:::dafug");
}
return "/config.jsp?mode=guest";
}
public void processAction(PortletConfig config, ActionRequest actionRequest, ActionResponse actionResponse) throws Exception {
conf.Names.clear();
String count = ParamUtil.getString(actionRequest, "count");
String portletResource = ParamUtil.getString(actionRequest, "portletResource");
PortletPreferences prefs = PortletPreferencesFactoryUtil.getPortletSetup(actionRequest, portletResource);
String[] list=count.split("/");
for(String a : list){
if( a!=null&& !a.equals("")){
String en = ParamUtil.getString(actionRequest,"En"+a);
String pa = ParamUtil.getString(actionRequest,"Pa"+a);
if(!en.equals("")&&!pa.equals("")){
conf.Names.put(pa,en);
log.info("word::"+en+"::::"+pa);
prefs.setValue("En"+a,en);
prefs.setValue("Pa"+a,pa);
}else if(a!=null&& !a.equals("")){
count=count.substring(0,count.lastIndexOf("/"+a))+count.substring(count.lastIndexOf("/"+a)+("/"+a).length());
}
}
}
prefs.setValue("count",count);
prefs.store();
}
public void serveResource(ResourceRequest request, ResourceResponse response){
log.info("HERE in conf");
}
}
This class worked fine for only one time after clicking on return to full page, the button that locate in right corner of portlets does not work and I cannot go to configuration page again!
and also the menu bar in up right corner of portal did not work after getting back from configuration page unless I delete my portlet and all of them will work fine again!
I solved this problem.
My problem is that first I should change all the to
and I change all of my JQuery code to JavaScript because some how these version of JQuery that I used generates some error with this version of Liferay (5.2.3)

Resources