Showing posts with label how-to. Show all posts
Showing posts with label how-to. Show all posts

Thursday, October 21, 2010

Liferay Import - Large LAR's

Technical Details:

LAR = 111M (326 pages)
Uploaded on local dev system running Win XP using FF 3.6.8
Liferay 5.2.3 Bundle with Tomcat 6
Postgres database

Scenario:

Copy info from the Guest Community into a new Community for setup with Virtual Hosting.

Action:

It's important to keep in mind that Liferay has max file sizes that can be uploaded and that also includes a threshold for the input stream. In my case, a default export resulted in a LAR that was 111M (326 pages). To accommodate this size, the following was put in to ROOT\WEB-INF\classes\portal-ext.properties (I bloated the size more than needed intentionally):
# Set the maximum file size. Default is 1024 * 1024 * 100. (default 104857600)
com.liferay.portal.upload.UploadServletRequestImpl.max.size=209857600
# Set the threshold size to prevent out of memory exceptions caused by
# caching excessively large uploaded data. Default is 1024 * 1024 * 10. (default 104857600)
com.liferay.portal.upload.LiferayInputStream.threshold.size=209857600
The next step was to go to Control Panel -> Server Administration -> File Uploads. There, I marked all file sizes as 0 (unlimited). Alternatively, you can mark the sizes in the portal-ext.properties as well (Ex. dl.file.max.size=0 , ig.image.max.size=0 , journal.image.small.max.size=0)

REBOOT Tomcat (important!)

Then do the import as you normally would.

Lessons Learnt:

-Strange but true, IE (8) and FF show different error strack traces. Browser wise, In most cases, IE would throw up a 404 error on failure where FF retained the current page and Liferay threw up a catch-all error message.
-At one point, I also tested on a remote system. After an eon, the system asked if I wanted to extend my session and I clicked yes. Just at that time, I got an error message as posted in LPS-10837.
-For kicks, I tried importing the Postgres-based LAR file into a MySQL database. Interestingly, the error message it threw was the SAME error message as reported by Josh Asbury in LPS-1981. In that ticket, Josh blames the error on a missing UTF8 character set however, it looks like the same error is tripped if importing from incompatible databases. (My stack trace at the bottom.)

In Conclusion:

The Export/Import feature is a necessity but God, it's cranky!

Good luck!

The following was MY stack trace:

13:40:54,121 ERROR [JDBCExceptionReporter:101] Incorrect string value: '\xEF\xBF\xBDs, ...' for column 'content' at row 1
13:40:54,277 ERROR [ImportPagesAction:85] com.liferay.portal.SystemException: com.liferay.portal.lar.PortletDataException: com.liferay.portal.SystemException: com.l
rnel.dao.orm.ORMException: Could not execute JDBC batch update
com.liferay.portal.SystemException: com.liferay.portal.lar.PortletDataException: com.liferay.portal.SystemException: com.liferay.portal.kernel.dao.orm.ORMException:
te JDBC batch update
at com.liferay.portal.lar.PortletImporter.importPortletData(PortletImporter.java:467)
at com.liferay.portal.lar.PortletImporter.importPortletData(PortletImporter.java:367)
at com.liferay.portal.lar.LayoutImporter.importLayouts(LayoutImporter.java:627)
at com.liferay.portal.service.impl.LayoutLocalServiceImpl.importLayouts(LayoutLocalServiceImpl.java:625)
at com.liferay.portal.service.impl.LayoutLocalServiceImpl.importLayouts(LayoutLocalServiceImpl.java:596)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy25.importLayouts(Unknown Source)
at com.liferay.portal.service.impl.LayoutServiceImpl.importLayouts(LayoutServiceImpl.java:210)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy26.importLayouts(Unknown Source)
at com.liferay.portal.service.LayoutServiceUtil.importLayouts(LayoutServiceUtil.java:160)
at com.liferay.portlet.communities.action.ImportPagesAction.processAction(ImportPagesAction.java:73)
at com.liferay.portal.struts.PortletRequestProcessor.process(PortletRequestProcessor.java:180)
at com.liferay.portlet.StrutsPortlet.processAction(StrutsPortlet.java:197)
at com.sun.portal.portletcontainer.appengine.filter.FilterChainImpl.doFilter(FilterChainImpl.java:98)
at com.liferay.portal.kernel.portlet.PortletFilterUtil.doFilter(PortletFilterUtil.java:57)
at com.liferay.portlet.InvokerPortletImpl.invoke(InvokerPortletImpl.java:632)
at com.liferay.portlet.InvokerPortletImpl.invokeAction(InvokerPortletImpl.java:664)
at com.liferay.portlet.InvokerPortletImpl.processAction(InvokerPortletImpl.java:359)
at com.liferay.portal.action.LayoutAction.processPortletRequest(LayoutAction.java:604)
at com.liferay.portal.action.LayoutAction.processLayout(LayoutAction.java:428)
at com.liferay.portal.action.LayoutAction.execute(LayoutAction.java:195)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:431)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:236)
at com.liferay.portal.struts.PortalRequestProcessor.process(PortalRequestProcessor.java:157)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at com.liferay.portal.servlet.MainServlet.callParentService(MainServlet.java:608)
at com.liferay.portal.servlet.MainServlet.service(MainServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:630)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:436)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:374)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)
at com.liferay.portal.servlet.FriendlyURLServlet.service(FriendlyURLServlet.java:143)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:154)
at com.liferay.portal.servlet.filters.strip.StripFilter.processFilter(StripFilter.java:142)
at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:91)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:154)
at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:94)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:154)
at com.liferay.portal.servlet.filters.gzip.GZipFilter.processFilter(GZipFilter.java:140)
at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:91)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:154)
at com.liferay.portal.servlet.filters.secure.SecureFilter.processFilter(SecureFilter.java:282)
at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:91)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:154)
at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:94)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:154)
at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:94)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:154)
at com.liferay.portal.servlet.filters.autologin.AutoLoginFilter.processFilter(AutoLoginFilter.java:257)
at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:91)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:154)
at com.liferay.portal.servlet.filters.sso.opensso.OpenSSOFilter.processFilter(OpenSSOFilter.java:73)
at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:91)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:154)
at com.liferay.portal.sharepoint.SharepointFilter.processFilter(SharepointFilter.java:193)
at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:91)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:154)
at com.liferay.portal.servlet.filters.virtualhost.VirtualHostFilter.doFilter(VirtualHostFilter.java:191)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:154)
at com.liferay.portal.servlet.filters.threadlocalcache.ThreadLocalCacheFilter.processFilter(ThreadLocalCacheFilter.java:55)
at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:91)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:154)
at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:94)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:738)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:433)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:595)
Caused by: com.liferay.portal.lar.PortletDataException: com.liferay.portal.SystemException: com.liferay.portal.kernel.dao.orm.ORMException: Could not execute JDBC b
at com.liferay.portlet.journal.lar.JournalPortletDataHandlerImpl.importData(JournalPortletDataHandlerImpl.java:1512)
at com.liferay.portal.lar.PortletImporter.importPortletData(PortletImporter.java:462)
... 131 more
Caused by: com.liferay.portal.SystemException: com.liferay.portal.kernel.dao.orm.ORMException: Could not execute JDBC batch update
at com.liferay.portal.service.persistence.impl.BasePersistenceImpl.processException(BasePersistenceImpl.java:91)
at com.liferay.portlet.journal.service.persistence.JournalArticlePersistenceImpl.findByG_A(JournalArticlePersistenceImpl.java:1973)
at com.liferay.portlet.journal.service.impl.JournalArticleLocalServiceImpl.updateUrlTitles(JournalArticleLocalServiceImpl.java:2696)
at com.liferay.portlet.journal.service.impl.JournalArticleLocalServiceImpl.addArticle(JournalArticleLocalServiceImpl.java:298)
at sun.reflect.GeneratedMethodAccessor588.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:77)
at com.liferay.portal.mirage.aop.MirageInvoker.invoke(MirageInvoker.java:47)
at com.liferay.portal.mirage.aop.ContentInvoker.invoke(ContentInvoker.java:47)
at com.liferay.portal.mirage.service.ContentServiceImpl.process(ContentServiceImpl.java:247)
at com.liferay.portal.mirage.service.ContentServiceImpl.createContent(ContentServiceImpl.java:111)
at sun.reflect.GeneratedMethodAccessor587.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:77)
at com.liferay.portal.spring.aop.LogAdvice.invoke(LogAdvice.java:73)
at sun.reflect.GeneratedMethodAccessor365.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:627)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:616)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:64)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy204.createContent(Unknown Source)
at com.liferay.portal.mirage.aop.JournalArticleLocalServiceAdvice.doInvoke(JournalArticleLocalServiceAdvice.java:60)
at com.liferay.portal.mirage.aop.BaseMirageAdvice.invoke(BaseMirageAdvice.java:47)
at sun.reflect.GeneratedMethodAccessor238.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:627)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:616)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:64)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy146.addArticle(Unknown Source)
at com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil.addArticle(JournalArticleLocalServiceUtil.java:188)
at com.liferay.portlet.journal.lar.JournalPortletDataHandlerImpl.importArticle(JournalPortletDataHandlerImpl.java:823)
at com.liferay.portlet.journal.lar.JournalPortletDataHandlerImpl.importData(JournalPortletDataHandlerImpl.java:1407)
... 132 more
Caused by: com.liferay.portal.kernel.dao.orm.ORMException: Could not execute JDBC batch update
at com.liferay.portal.dao.orm.hibernate.ExceptionTranslator.translate(ExceptionTranslator.java:41)
at com.liferay.portal.dao.orm.hibernate.QueryImpl.list(QueryImpl.java:89)
at com.liferay.portal.dao.orm.hibernate.QueryImpl.list(QueryImpl.java:74)
at com.liferay.portlet.journal.service.persistence.JournalArticlePersistenceImpl.findByG_A(JournalArticlePersistenceImpl.java:1970)
... 182 more





 

Tuesday, October 20, 2009

Liferay 5.2.3 - Change Navigation to an Accordian

1. Change the navigation.vm file in your theme to the following (Note, change the options for different effects):

<script type="text/javascript">
jQuery().ready(function(){
jQuery('#accordian-nav').accordion({
active: false,
header: '.head',
event: 'mouseover',
fillSpace: true,
active: '.selected',
animated: 'easeslide'
});

});

</script>

<div id="navi" class="sort-pages modify-pages">
<ul id="accordian-nav">
#foreach ($nav_item in $nav_items)
#if ($nav_item.isSelected())
#set ($nav_item_class = "selected")
#else
#set ($nav_item_class = "")
#end

<li class="$nav_item_class">
<a class="head" href="$nav_item.getURL()" $nav_item.getTarget()><span>$nav_item.getName()</span></a>

#if ($nav_item.hasChildren())
<ul class="">
#foreach ($nav_child in $nav_item.getChildren())
#if ($nav_child.isSelected())
#set ($nav_child_class = "selected")
#else
#set ($nav_child_class = "")
#end

<li class="$nav_child_class">
<a href="$nav_child.getURL()" $nav_child.getTarget()>$nav_child.getName()</a>
</li>
#end
</ul>
#end
</li>
#end
</ul>
</div>

2. Add the CSS to your custom.css file (You'll definitely want to modify the colors):

/* Accordian Navigation */
#navi {
border:1px solid #5263AB;
margin:0px;
padding:0px;
text-indent:0px;
width:200px;
}
#navi a.head {
cursor:pointer;
border:1px solid #43AEE4;
color:#336699;
display:block;
font-weight:bold;
margin:0px;
padding:0px;
text-indent:14px;
text-decoration: none;
background-color: green;
}
#navi a.head:hover {
color:#000;
}
#navi a.selected {


}
#navi a.current {
background-color:#FFFF99;
}
#navi ul {
border-width:0px;
margin:0px;
padding:0px;
text-indent:0px;
height: auto!important
}
#navi li {
list-style:none outside none; display:inline;
}
#navi li li a {
color:#000000;
display:block;
text-indent:10px;
text-decoration: none;
}
#navi li li a:hover {
background-color: #E3F1FA;
color:#FF0000;
}

Example:



The only thing I don't particularly care for at this stage is that it moves all content items down. Solvable, but good enough for now. ;)

Only tested in IE7 and FF3

Monday, October 19, 2009

Installing Liferay 5.2.3 Using Postgres 8

1. Install and create lportal database (Note: for this example I used lportal523)

- Open pgAdmin III (Start Menu on Win Systems)
- Enter the name you want to use for the database (ex. lportal523)




















2. Download the appropriate driver version and place in lib/ext

Version 3:
Use this if you're running JVM 1.5
http://jdbc.postgresql.org/download/postgresql-8.4-701.jdbc3.jar

Version 4:

Use this if you're running JVM 1.6

http://jdbc.postgresql.org/download/postgresql-8.4-701.jdbc4.jar

Keep in mind that if you're using the Liferay bundle defaults, you're using JVM 1.5.

3. Set the properties in the portal-ext.properties file

jdbc.default.driverClassName=org.postgresql.Driver
jdbc.default.url=jdbc:postgresql://localhost:5432/lportal523
jdbc.default.username=postgres
jdbc.default.password=whateveryourpasswordis

4. Startup Liferay. Your database will look like this:



Enjoy!

Thursday, October 15, 2009

Updated Jan 2010: Liferay - Cool Breadcrumb

I decided to update this after I found some problems with the original method I had posted. Liferay uses breadcrumb styles 1 and 2 for other things for which I did not want to use the apple style but in addition, I've made it into a self-contained cool crumb. This solution is designed to work from directly in the theme and has been tested in 5.2.3.

So you want a cool looking breadcrumb? Perhaps one that's kind of Applish? Well these instructions will get you what you want.





1. Create a file in webapps\ROOT\html. For this example we'll call it crumb.jsp and place the following in it:

<%@ include file="/html/taglib/ui/breadcrumb/init.jsp" %>

<%
StringBuilder sb = new StringBuilder();
sb.append("<ul class='breadcrumb2'>");
_buildBreadcrumb(selLayout, selLayoutParam, portletURL, themeDisplay, true, sb);
%>

<%= sb.toString() %>

<%!
private void _buildBreadcrumb(Layout selLayout, String selLayoutParam, PortletURL portletURL, ThemeDisplay themeDisplay, boolean selectedLayout, StringBuilder sb) throws Exception {

String layoutURL = _getBreadcrumbLayoutURL(selLayout, selLayoutParam, portletURL, themeDisplay);
String target = PortalUtil.getLayoutTarget(selLayout);

StringBuilder breadCrumbSB = new StringBuilder();

breadCrumbSB.append("<li><a href=\"");
breadCrumbSB.append(layoutURL);
breadCrumbSB.append("\" ");
breadCrumbSB.append(target);
breadCrumbSB.append(">");

breadCrumbSB.append(HtmlUtil.escape(selLayout.getName(themeDisplay.getLocale())));

breadCrumbSB.append("</a></li>");


Layout layoutParent = null;
long layoutParentId = selLayout.getParentLayoutId();
if (layoutParentId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
layoutParent = LayoutLocalServiceUtil.getLayout(selLayout.getGroupId(), selLayout.isPrivateLayout(), layoutParentId);
_buildBreadcrumb(layoutParent, selLayoutParam, portletURL, themeDisplay, false, sb);


sb.append(breadCrumbSB.toString()+"");
}
else {
sb.append(breadCrumbSB.toString()+"");
}
}

private String _getBreadcrumbLayoutURL(Layout selLayout, String selLayoutParam, PortletURL portletURL, ThemeDisplay themeDisplay) throws Exception {
if (portletURL == null) {
return PortalUtil.getLayoutURL(selLayout, themeDisplay);
}
else {
portletURL.setParameter(selLayoutParam, String.valueOf(selLayout.getPlid()));

return portletURL.toString();
}
}
%>


2. In your custom.css file add the following (remember to change the urls to your server):

.breadcrumb2
{
font: 11px Arial, Helvetica, sans-serif;
background-image:url('../images/theme1/bc_bg.png');
background-repeat:repeat-x;
height:30px;
line-height:30px;
color:#9b9b9b;
border:solid 1px #cacaca;
width:100%;
overflow:hidden;
margin:0px;
padding:0px;
}


.breadcrumb2 li
{
list-style-type:none;
float:left;
padding-left:10px;
}

.breadcrumb2 a
{
height:30px;
display:block;
background-image:url('../images/theme1/bc_separator.png');
background-repeat:no-repeat;
background-position:right;
padding-right: 15px;
text-decoration: none;
color:#454545;
}
.breadcrumb2 a:hover
{
color:#35acc5;
}
.home
{
border: none;
margin: 8px 0px;
}

3. Last but not least, here are the images:





This last part will include your new breadcrumb on all pages. Open the portal_normal.vm and include:

$theme.include("/html/crumb.jsp")


GenericPortlet & Ajax

Anyone familiar with form submission knows that the processAction takes care of the processing as far as the backend goes but in case you're wondering how to process an Ajax call, look no further.

In your JSP, you must use the ResourceURL ()

ResourceURL resourceURL = renderResponse.createResourceURL();


For this quick example, I use JavaScript to handle the call:



function delFav(thisFav) {
if(confirm("This will delete your favourite. Are you sure you want to continue?")) {
$("div#showaddfav").html(" Deleting your favourite. Please wait.");
$.post("<%=resourceURL%>", { delFav: thisFav, usersId: "<%=themeDisplay.getUserId()%>" },
function(data){

if(checkType("del-saved", data) != -1) { $("#showaddfav").html("<span class="portlet-msg-success">Your favourite was deleted. Congrats!</span>"); }
if(checkType("error", data) != -1) { $("#showaddfav").html("<span class="portlet-msg-error">An unknown error has occured. Please notify the Administrator.</span>"); }
});
} else { return; }

}

function checkType(expr, thisUrl) {
return thisUrl.search(expr);
}


And your portlet should use the serveResource for processing:



import java.io.PrintWriter;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;

public void serveResource(ResourceRequest req, ResourceResponse resp)
throws PortletException, IOException {
resp.setContentType("text/html");
PrintWriter writer = resp.getWriter();

// User want to delete
String delFav = ParamUtil.getString(req, "delFav");

try {

writer.print("<div id="response-wrap">del-saved</div>");

} catch (PortalException e) {
writer.print(" <div id="response-wrap">error</div>");
e.printStackTrace();
} catch (SystemException e) {
writer.print(" <div id="response-wrap">error</div>");
e.printStackTrace();
}
writer.close();
}




This of course is just example code but if you want to pass a tidbit of info back to your jsp you have to use the print (and don't forget to close the writer).

Wednesday, October 14, 2009

How to Localize a Browse Button

Yes, I have seen more complaints about this than you can image but the good news is not only can you 'localize' it but make it pretty. Wanna see what I'm talking about?


In case you're not familiar with the problem, a form input type of "file" connects to the client's operating system via an Application Programming Interface (API). That familiar window that allows us to select our file is displayed depending on your operating system (*nix, Windows, Mac). Because of this, it was deemed as a security risk to allow a developer to interfere in any way with this functionality.

What browser will this work on?

First and foremost, this will work in IE 6 and 7, FF 2 and 3, and Safari on MAC.

What you need


1) 2 Images: One to display English one to display French. (Or whatever languages you choose.)


Admittedly, these aren't pretty but they'll do. The file name you give your images plays a roll (well at least for this example). The English one I've called browseen_US and browsefr_FR. Why? Because when we swap (by pressing the French or English link) the buttons will swap based on locale. In addition, the image dimensions should stay the same. In this case they're not quite the same so you can see the difference.

2) The Code (Read the comments throughout)


<html>
<head>
<script type="text/javascript">
//Set your default language
var myLang="fr_FR";

//The 'switchTo...' functions will be triggered when we select the
//English or French link.
//The call to initFileUploads updates the UI.
function switchToEnglish() {
myLang="en_US";
initFileUploads();
}

function switchToFrench() {
myLang="fr_FR";
initFileUploads();
}

//This function will update the UI. Note this is where the magic happens.
//We will be using a regular file input type but we use a combination
//of CSS and JavaScript to overlay the English and French buttons.
function initFileUploads() {

var fakeFileUpload = document.createElement('div');

fakeFileUpload.className = 'fakefile';
fakeFileUpload.appendChild(document.createElement('input'));
var image = document.createElement('img');

image.src='browse'+myLang+'.jpg';
image.id="uploadImgId";

fakeFileUpload.appendChild(image);
var x = document.getElementsByTagName('input');

for (var i=0;i<x.length;i++) {
if (x[i].type != 'file') continue;
if (x[i].parentNode.className != 'fileinputs') continue;
x[i].className = 'file hidden';
var clone = fakeFileUpload.cloneNode(true);
x[i].parentNode.appendChild(clone);
x[i].relatedElement = clone.getElementsByTagName('input')[0];
x[i].onchange = x[i].onmouseout = function () {
this.relatedElement.value = this.value;
}
}
}

//This function is called just as a test to see what will be submitted.
//The output will be different depending on the browser you're using.
function viewSubmit() {
for(i=0; i<document.browseTest.elements.length; i++) {
if(document.browseTest.elements[i].name == "") {
document.write("This is the dynamically generated input. ---- ");
}
document.write("The field name is: " + document.browseTest.elements[i].name + " and it’s value is: " + document.browseTest.elements[i].value + ".<br />");
}
}
</script>

<!--These styles are needed for the magic to work. You may have to adapt these depending on what browser you need this to work in. -- >
<style type="text/css">
div.fileinputs {
position: relative;
/*ie7 and ff2 are colliding*/
width: auto;
}

div.fileinputs .file {
/*For ie7 only*/
width: 235px;
}

div.fakefile {
position: absolute;
top: 0px;
left: 0px;
z-index: 1;
}

input.file {
position: relative;
text-align: right;
-moz-opacity:0 ;
filter:alpha(opacity: 0);
opacity: 0;
/*Required for ff2 ONLY*/
width: 145px;
z-index: 2;
}

#uploadImgId {
position: absolute;
/*ie 7 needs this*/
width: 90px;
}

</style>
</head>

<!--The initFileUploads is called to update the UI upon entering the page. -->
<body onload="initFileUploads();">

<fieldset><legend>Browse Button Localization</legend>
Select Language: <a href="#" onclick="switchToEnglish()">English</a>
<a href="javascript:switchToFrench()">French</a><p>

<form name="browseTest" class="example">
<div class="fileinputs">
<input type="file" class="file" name="originalFileInput"/>
</div>

<br />
<input type="button" name="submit" value="View the Submission Value" onclick="viewSubmit()">
</form>
</fieldset>

</body>
</html>

Feel free to swipe!