Liferay 6 Certification Preparation Tips

      No Comments on Liferay 6 Certification Preparation Tips

How to prepare

  • There is no shortcut. Don’t rely on any sample questions online(including this post) completely. Best way to prepare is to practice tutorial here . Even the experienced developers should try to go through the tutorial, try to create portlets, hooks and learn the concepts by doing things.
  • One question will definitely come from this blog post
  • At least 1-3 question will be around Liferay Lifecycle, Phases, Modes and States. Learn which ones are introduced in JSR-286
  • Hooks Hooks Hooks learn as much as possible about hooks.
  • Especially whether or not and how it can implement core JSP overwrites and custom action.
  • Learn about the tags in the liferay-hook.xml
  • Learn APIs for Util and User – for e.g., how to get organizations for a user OrganlizationServiceUtil.getUserOrganizations(long userId)
  • Learn about EXT practices – how to cleanly deploy in the production environment and how to deploy in development environment
  • liferay-portlet.xml, portlet.xml, portlet-custom.xml, portlet-ext.xml, liferay-plugin-package.properties, liferay-look-and-feel.xml – you understand about these files when you learn about them individually. But when you appear for the exam it is very very confusing.
  • Ext vs Hook. Be very clear what can be done in hook and what can be done in EXT. The exam comes to this tricky issue again and again
  • Don’t under estimate Layout Template and Theme sections. Read it from developer guide. It’s an easy win
  • It is a good idea to look into liferay-hook dtd and portal.properties. But practically speaking you won’t be able to remember all the possible portal-properties. Objective is to learn about as many of them as possible
Example Questions(Not exact questions from actual exams)
Architecture
  • What is true – class in plugin has access to every class in portal, every class in portal-service plus plugin class, every class in portal-impl.jar plus plugin class etc.
  • What has to be done to prevent submission of form again?
  • What happens after a portlets action is called. Options are – render of only that portlet is called, render of all portlets on the page is called, render of any portlet whose data changed is called.
  • Expando is – service available to add custom attributes
  • How to get organizations associated to a user. Options are UserServiceUtil, OrganizationServiceUtil, SiteServiceUtil, All of the above etc. I have answered UserLocalServiceUtil.getOrganizations() .
    • The right answer is OrganlizationServiceUtil.getUserOrganizations(long userId)
  • companyId is – options are organization, site, portal etc.
    • Right answer – companyId represents a portal instance. Liferay can host multiple portals in a single database. companyId is primary key for a particular instance. In scope terms companyId is on top of the hierarchy, followed by GroupID which represents site or organization and then UserId, which identifies a user
  • There is a plugin portlet which required another plugin portlet how to ensure that.
    • Answer – is you will use  required-deployment-contexts in liferay-plugin-packages.properties. LEARN MORE about it.
Hooks
  • There was a question about removing a portlet from whitelist which is mentioned in portal.properties of the Portal. portlet.add.default.resource.check.whitelist . To remove one of the portlets from whitelist what has to be done.
    • This is important. Hooks can just add to the whitelist because properties are merged. To remove, you may have to create ext. Some properties are just mergeable not overrideable
  • Language properties for a locale en_Us is implemented. Now the language values for that particular locale will come from
    • Yes, the answer is plugin’s Language_en plus core Language_en
  • If you have to add a new field for indexing what would you do?
    • I think indexer post processor hook should do it.
  • What is the syntax for a custom-struts path in hook? I think I have answered this correctly. <!ELEMENT struts-action (struts-action-path, struts-action-impl)>. It involves structs-action-path root element with struts-action-path and struts-action-impl
  • When you override a JSP say view.jsp using hook what happens to original JSP.
    • Answer is that it gets replaced with view.portal.jsp
Layout templates
  • two questions on how to include portlet plugin in layout template – $processor.processPortlet with Fully Qualified Portlet Id
    • Please note that in theme you will include using theme.runtime(..)
Portlet
  • Syntax of <liferay-ui:success key=”key” message=”message” /> was asked. I thought only key attribute is required.
    • As per dtd both key and message are required
  • How to escape special characters. For such questions, please learn about important utility methods in the following
    •  HtmlUtil
    • ParamUtil
    • GetterUtil
Development practices
Themes
  • how the base theme settings are imported.
    • Just set theme.parent in build.xml
  • Javascript method called after each portlet is executed.
    • Right answer is Liferay.Portlet.ready(fn) . This is an important question. This comes in one way or another. Link
  • AlloyUI is based on – answer is YUI3
  • How to remove portlet borders in custom theme
  • How to embed a portlet in theme. Answer is theme.runtime()
EXT
  • Best way to undeploy / redeploy ext hook – I think best is to unzip clean portal
  • Best way to remove some customization from ext and deploy changes in development environment .
Service Builder
  • What are the services available/injected to each service generated by service builder. CounterLocalService, AssetLocalService, ResourceLocalService and two more..
    • Counter
    • Resource
    • User
Others
  • There was one question where they wanted to strip out something from returned response. where can we do it? options were Request post processor in hook/ext, servlet filters, post action etc
    • It could be done by StripFilter and if the requirement is not met by that we can use servletfilter
    • It’s interesting, servlet filters can be used for both requests and responses
  • If you have to run a code which has to be run just once, where will you put it.
  • If you want to remove some core portlet from Add Portlet option to control panel what will you do.
  • A service.xml mapping was shown with entity something and localservice=true and remoteservice=false was asked what classes will be generated. In general, it’s better to understand what are the different classes which are generated in various options
    • Take example of Event entity
      • Persistence
        • EventPersistence
        • EventPersistenceImpl
        • EventUtil
      • Local Service
        • EventLocalService
        • EventLocalServiceImpl(CLASS TO BE MANUALLY CHANGED)
        • EventLocalServiceBaseImpl
        • EventLocalServiceUtil
        • EventLocalServiceWrapper
      • Remote Service
        • EventService
        • EventServiceImpl(CLASS TO BE MANUALLY CHANGED)
        • EventServiceBaseImpl
        • EventServiceUtil
        • EventServiceWrapper
        • EventServiceSoap
        • EventSoap
      • Model
        • EventModel
        • EventModelImpl
        • Event
        • EventImpl(CLASS TO BE MANUALLY CHANGED)
        • EventWrapper
  • You have to update core jsps for Document and Media portlet. Where will you do it.
  • You have to implement a solution involving lot of core JSP changes and a custom action what would you do.
    • I don’t remember the exact question. but if the question is intending to ask what to do if we have to override multiple JSPs. I think the answer is that the best approach is to have all the customization in one hook.
Some notes
Portlet
Hook
– Generally overrides web resources found int portal-web – asp, jspf, javascript , css, images
– JSPF changes won’t take effect unless you modify the JSP that includes it
– CSS – you have to modify the css which includes it. just changing sub-css won’t work
– Portal Properties
— Model Listeners
— Validators
— Generators
— Content Sanitizers
– Override and define Struts actions
– Override portal services for e.g. MyUserLocalServiceImpl
– Language properties
– Search summaries, indexes and queries (index post processor)
– Servlet filter hooks – pre and post actions
Summary
Hooks are used to modify
– Portal Properties (Not all, only those listed in dtd)
– Language properties
– JSP files
– Index post processor
– Services
– Servlet filter
– Struts action
<!ELEMENT hook (portal-properties?, language-properties*, custom-jsp-dir?,
custom-jsp-global?, indexer-post-processor*, service*, servlet-filter*,
servlet-filter-mapping*, struts-action*)>
Ext
Steps for Application Display templates
  1. Create a *PortletDisplayHandler
  2. Register the hander in liferay-portlet.xml using <template-handler> tag
  3. Assign ADD_PORTLET_DISPLAY_TEMPLATE permissions in resource-actions/default.xml
  4. In your configuration JSP use <liferay-ui:ddm-template-selector> in the tag classNameId is what specifies your template
  5. Update view.jsp accordingly
Liferay Portlets Lifecycle
  1. void init(PortletConfig config) in GenericPortlet and init() in MVCPortlet
  2. void render(RenderRequest request, RenderResponse response)
  3. void processAction(ActionRequest request, ActionResponse response)
  4. void processEvent(EventRequest request, EventResponse response)
  5. void serveResource(ResourceRequest request, ResourceResponse response)
  6. void destroy()
GenericPortlet implements Portlet
LiferayPortlet extends GenericPortlet
MVCPortlet extends LiferayPortlet
Liferay Portlets Phases
  1. Render Phase (168)
  2. Action Phase(168)
  3. Event Phase(286)
  4. Resource Serving Phase(286)
Portlet Modes
  1. View
  2. Edit
  3. Help
Portlet Window States
  1. Normal
  2. Maximized
  3. Minimized
Services Injected by Service Builder
  1. counterService
  2. resourceService
  3. userService

 

“A Cloud Guru” vs “Linux Academy” vs CloudAcademy

Disclaimer – This post is based on my personal experience. I have spent more than 8 months with A Cloud Guru and just a few weeks with other two services – Linux Academy and CloudAcademy. I am NOT associated or affiliated with any of the services and/or product mentioned in the post. If I have misrepresented anything please let me know via comments.

 A Cloud GuruLinux AcademyCloudAcademy
Pricing ModelYou buy a particular course and you get lifetime access to the course contentsYou get access to the website. As long as you have the access, you can access all the courses. You can start with a trial version which gives you full accessYou get access to the website. As long as you have the access, you can access all the courses. You can start with a trial version which gives you full access
Courses / ContentMostly AWS and cloud related courseWide variety of courses - AWS, Linux, Big Data, Devops, Azure etcCloud based courses - including AWS, Azure and Google Cloud.
AWS Solution Architect Practice Exams/QuizzesAs of January 2017, it has 1 mini exam, 1 practice exam and 11 quizzes. Almost all topics have quizzesAs of Jaunary 2017, it has just two quizzes - overview quiz and S3 quiz and 1 practice examAs of April 2017, it has 15 Video Courses, 9 Quiz Sessions and 9 Hands-On Labs
LabsCourse videos have labs for most of the topics, you have to follow the video and complete the labCourse has 9 Live Labs . You can launch and do the live lab in the AWS account created by you by the courseCourse has 9 Hands on labs.
Mobile SupportYou can watch the videos on your mobile device and that's about it. There is no app.They have a pretty decent mobile appCloudAcademy has the best mobile app of them

Choice

I will leave the final decision to you. But in my opinion, you can go with this plan

  • I think A Cloud Guru courses are a must. Here are the benefits
    • Videos are high-quality content and it covers the subject in great depth where required.
    • Videos are created with certifications in mind. So you know what is the scope of certification for any given topic.
    • Once you buy a course it stays with you. With this, you don’t have a time limit within which you have to finish the course. Not only that, you can refer to the videos even after the certification is done.
  • If you are willing to learn from one other source then choose any one of Linux Academy or cloudacademy.com. You can choose both and start with a trial and continue with whichever one you like. Make sure in the trial period you finish all the quizzes and the courses/topics which are not covered by A Cloud Guru in sufficient details(remember the goal is to gain knowledge, not just certification). Remember to download apps for the corresponding course while in the trial period so you can evaluate that aspect of the offering too.

General Certification Tips

  1. Give ample time to yourself to prep for the certification. If you are aware of work with AWS features already then you need 1-2 months to prepare. If you are new to AWS then you will need more. Much more.
  2. Do all the quizzes. Repeat. Do all the quizzes again and again. Repeat as long as you don’t get 100% on the quizzes. Some of the questions on the exam are picked directly from the quizzes. Google for AWS quiz and do some of those too.
  3. Try some mobile apps. Other than the CloudAcademy and LinuxAcademy apps above, I had two more apps on my Android phone. “AWS Tests” and “AWS-Solutions Arch Associate”. These apps are no longer on play store I think. But you can try other apps out there. The benefits of the mobile apps are that you can do a few quizzes, revise some concepts if you have 5-10 minutes of free time. I used these apps before going to bed or in mid of the night when I can’t sleep but too lazy to pick-up a book :). I have read not-so-great reviews about acloudguru mobile app. So use your judgment before spending any money on that.
  4. You have to finish FAQs and Whitepapers as much as you can
  5. If you are into Live/In-person classes then you can try out http://awspro.academy/. They will send you a free copy of the Developer Guide.
  6. Read the forums on acloudguru and other sites to know what kind of questions are being asked.

Default profile (default.properties) for Patching Liferay on Jboss

You can always use patching tool’s auto-discovery option to generate a profile. In case you are not able to use that following are the sample settings for JBoss. Just create default.properties under patching-tool directory

Key properties to remember are war.path which should point to your ROOT.war directory and global.lib.path which should point to your jar directory

Note: Tested with liferay 6.2 and Jboss 6.4. Example is for Windows OS but same should work for Unix based environments

Tomcat – How to resolve java.util.zip.ZipException: error in opening zip file

This post is not necessarily about any specific technology. Just wanted to tell you about one possible reason for this commonly faced problem. I was working on a Spring MVC application lately and I got the following error

SEVERE [localhost-startStop-4] org.apache.catalina.core.ContainerBase.addChildInternal ContainerBase.addChild: start:
org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/springcaptcha]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:153)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:940)
at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1816)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [org.apache.catalina.webresources.StandardRoot@70d8c322]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:153)
at org.apache.catalina.core.StandardContext.resourcesStart(StandardContext.java:4958)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5088)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)
… 10 more
Caused by: org.apache.catalina.LifecycleException: Failed to initialize component [org.apache.catalina.webresources.JarResourceSet@2e94c523]
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:106)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:136)
at org.apache.catalina.webresources.StandardRoot.startInternal(StandardRoot.java:699)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)
… 13 more
Caused by: java.lang.IllegalArgumentException: java.util.zip.ZipException: error in opening zip file
at org.apache.catalina.webresources.JarResourceSet.initInternal(JarResourceSet.java:139)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
… 16 more
Caused by: java.util.zip.ZipException: error in opening zip file
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.<init>(ZipFile.java:219)
at java.util.zip.ZipFile.<init>(ZipFile.java:149)
at java.util.jar.JarFile.<init>(JarFile.java:166)
at java.util.jar.JarFile.<init>(JarFile.java:103)
at org.apache.catalina.webresources.JarResourceSet.initInternal(JarResourceSet.java:136)
… 17 more

Now, there could be various reasons why this could be happening. I am just going to tell how I resolved it.

I was using Maven for my builds and it happened that some of the dependency jars downloaded by Maven are not valid. They were Zero Byte, 1Byte jars. Obviously, Tomcat was trying to load those jars and was not able to do so. I resolved this error by manually copying jars from Maven Repos and changing some of the dependencies. In your case check if you can do the same.

Other Possible Reasons:

  • Check if your jar has proper permissions for the system user which is running Tomcat
  • Try to open the file in Zipeg , Winrar, Winzip or any equivalent unzipping system and verify if any of the jar in the classpath is not corrupt. Look for suspiciously smaller sized files

Patching Liferay Source Code

      No Comments on Patching Liferay Source Code

In Liferay development, it’s very useful to have Source Code available to you for the purpose of troubleshooting and debugging. This is especially useful when you get an error in the log on the server with a stack trace and a line number. With the source code, you can always look at the code and investigate in detail the root cause of the error. You can always download the Source Code of your portal from liferay.com and setup with your IDE(this is useful for local debugging with breakpoints)

However, this becomes challenging when you have Liferay EE subscription and you have applied patches to your portal. It is possible that your source code is out-of-date/out-of-sync with your deployed portal code. Luckily, Liferay patching tool provides you a way to patch your source code.

To begin, go to your patching-tool directory

Step 1:

Step 2:

Create a new profile to be used for patching the source code. To achieve this create patch-source.properties under patching-tool directory

In the above example, we have set a patching mode and location of the source code which has to be patched. For more details refer to the documentation or run ./patching-tool.sh help

Step 3

Run the patching tool with the custom profile created in above step. Since the name of our file was patch-source.properties our profile name is patch-source

 

 

Custom Display, Review and Expiry date in Liferay

Recently we had a requirement where we want all our new articles to go live next day, up for review in 6 months and automatically expire in 1 year. Of course, all this can be overriden by content authors at the time of content creation. But these are the defaults we wanted. To achieve this you have to override JournalArticle model hint as defined in portal-model-hints.xml. Here are the defaults in Liferay

To override this you will have to create an ext(unfortunately that’s the only way to go). In your ext’s ext-impl/src/META-INF folder create ext-model-hints.xml. Copy the <model name=”com.liferay.portlet.journal.model.JournalArticle”> section from portal-model-hints.xml and change the relevant settings. here are the changes we made to meet our needs

Multiple files upload in Liferay 6.1

Today I have found a weird bug in Liferay’s UploadServletRequestImpl in the following method

 

The intention of the above code is to return the full name of the file(s) being uploaded. But actually the above code returns the name of the first file uploaded on the form with the name field.

But what if I have multiple files uploads on my form with the same name like this

 

If you upload two files on the above form the following code will always print name of the first file

 

Workaround

You can use uploadPortletRequest.getMultipartParameterMap() to get all the multipart parameters for a parameter name. The following code will print the name of all the files

 

 

JournalVmUtil in Liferay 6.1

      No Comments on JournalVmUtil in Liferay 6.1

Disclaimer – Following is not the best or optimal solution. If you have better suggestion please write in comments

JournalVmUtil was present upto Liferay 5.2 and then deprecated in Liferay 6.0 and then completed removed in Liferay 6.1. If you are upgrading to 6.1 and make extensive use of JournalVmUtil you can do the following.

Extend VelocityTemplateParser.java. Following code example is just a sample. Feel free to add any pre-processing or post-processing as required

 

Now inject MyVelocityTemplateParserImpl in your velocity templates and just call getNodes method like this