GIT reset explained in details in a very easy to understand manner. Even if you think you know about git rest already, pretty sure you'll be surprised with that subtle insight you get after ready this article by the author of ProGit
Welcome to my blog where occasional rants,
grumble and mumble about things in life expressed
as code ...
... essentially my cat /dev/null ... ^_^!!
Friday, April 6, 2012
Friday, March 30, 2012
Sharing Liferay's Portal ClassLoader
It is possible to share Liferay Portal's ClassLoader with Liferay's plugins (eg. Portlets WARs and also independent Servlets)
Say if I have a Servlet called Servlet1 that was packaged in a separate WAR that I'd like to use Liferay Portal's classloader, I'd need to declare it as a PortalClassLoaderServlet through the following configurations in it's web.xml
PortalClassLoaderServlet com.liferay.portal.kernel.servlet.PortalClassLoaderServlet servlet-class foo.bar.Servlet1 100 PortalClassLoaderServlet /servlet1/*
With this declaration and with Liferay deployed as a separate WAR file, Servlet1 will be registered when Liferay starts up and is aware of Liferay Portal's lifecycle, and will get initialized and destroyed (through Servlet's init(ServletConfig) and destroy() methods respectively) when Liferay Portal startup and shutdown). When a request is being made to Servlet1, PortalClassLoaderServlet will act as a proxy that swaps the current request thread's context ClassLoader with the ClassLoader that Liferay Portal is started up with and so you get all the classes that comes with Liferay Portal.
Technically, i think it is possible to take this further and having PortalServlet loaded using the same classloader as Liferay Portal through the following web.xml configuration
MyPortal Servlet com.liferay.portal.kernel.servlet.PortalClassLoaderServlet servlet-class com.liferay.portal.kernel.servlet.PortletServlet portlet-class foo.bar.portlets.MyPortlet 100
But care must be taken to make sure classes that was used also exists in Liferay Portal WAR or in say Tomcat's public library classpath. Messing with ClassLoader is always hazardous and best to be avoided if possible. That's my 2 cents.
Friday, March 23, 2012
Liferay's 3 Servlets Musketeers (PortalActionServlet, PortalServlet and MainServlet)
This is the main servlet in Liferay, it handles all request directed to the portal itself, mapped to '/c/*' as in Liferay's ROOT web.xml. Together with various FriendlyURLServlet mappings in web.xml, they almost handle all the happenings in Liferay. FriendlyURLServlet normally analyze friendly urls and do a redirect after regenerating friendly urls back to the complex form that Liferay happens to understand through PortalUtil
PortletServletThis is the servlet that will get autogenerated during deployment of Portlet Plugins WAR file. It is really just a simple proxy pumping in resources to your portlet. Checkout PortletAutoDeployer on how it is written to your Portlet Plugin WAR's web.xml during hot deployment. Remember that the whole Portlet framework is after all based on Servlet specs, this Servlet gives Liferay a way to push through resources to a specific portlet.
PortalActionServletIn short, forget about this Servlet, it is a legacy Servlet as far as my understanding goes. Why? All it does is make sure a copy of PortletRequestProcessor (sounds familiar? yes, its an extension of Struts's RequestProcessor) is available in ServletContext under WebKey.PORTLET_STRUTS_PROCESSOR. This is now (Liferay 6.1.x) being taken care of in MainServlet.checkRequestProcessor method. Think of it this way. Where does your portlet lives? Inside a Portal container of course. Any request to your portlet have to go through a Portal container first, and that means going through MainServlet which will make sure a copy of PortletRequestProcessor is available nicely before eventually hitting your portlet. Humbly think that this is a nicer way rather than having each Portlet WAR file declaring a PortletActionServlet, cause the following is how PortletActionServlet stick a copy of PortletRequestProcessor into ServletContext
ServletContext servletContext = getServletContext();
ModuleConfig moduleConfig =
(ModuleConfig)servletContext.getAttribute(Globals.MODULE_KEY);
PortletRequestProcessor portletRequestProcessor =
PortletRequestProcessor.getInstance(this, moduleConfig);
servletContext.setAttribute(
WebKeys.PORTLET_STRUTS_PROCESSOR, portletRequestProcessor);
It's coupling in Struts's specific way of looking up ModuleConfig into it's code, which arguable isn't going to change much in the near future anyway but still ... I think it's tight coupling
This is how it's done in MainServlet.checkPortletRequestProcessor(...)
ServletContext servletContext = getServletContext();
PortletRequestProcessor portletReqProcessor =
(PortletRequestProcessor)servletContext.getAttribute(
WebKeys.PORTLET_STRUTS_PROCESSOR);
if (portletReqProcessor == null) {
ModuleConfig moduleConfig = getModuleConfig(request);
portletReqProcessor =
PortletRequestProcessor.getInstance(this, moduleConfig);
servletContext.setAttribute(
WebKeys.PORTLET_STRUTS_PROCESSOR, portletReqProcessor);
}
which is doing it through getModuleConfig(request) methods relying on Struts's ActionServlet to provide the implementation and hence abstracting it away from potential future changes in implementation
This are really just my understandings on briefly digging into Liferay's source through occasionally a VI on a terminal over a glass of red or coffee during spare times over lunch break or weekends. If you disagree in anyway, I'd love to be corrected.
Anyway Liferay looks like a promising portal solution and I would definitely be exploring further
Monday, March 12, 2012
Ever wonder how Liferay keeps track of it's WAR'ed Portlets
Friday, March 9, 2012
Ouch!! ... mvn liferay:build-service hurts ...
mvn liferay:build-service -P liferay-plugins-development
where liferay-plugins-development profile contains properties setting of my liferay version and deployment directory, and was bumped with the following exception
[INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO] ------------------------------------------------------------------------ [INFO] Total time: 17.172s [INFO] Finished at: Sat Mar 10 16:50:43 EST 2012 [INFO] Final Memory: 4M/15M [INFO] ------------------------------------------------------------------------ [ERROR] Failed to execute goal com.liferay.maven.plugins:liferay-maven-plugin:6.1.0:build-service (default-cli) on project myliferay-portlet: Execution default-cli of goal com.liferay.maven.plugins:liferay-maven-plugin:6.1.0:build-service failed: An API incompatibility was encountered while executing com.liferay.maven.plugins:liferay-maven-plugin:6.1.0:build-service: java.lang.AbstractMethodError: com.liferay.util.sl4fj.LiferayLoggerAdapter.log(Lorg/slf4j/Marker;Ljava/lang/String;ILjava/lang/String;Ljav/lang/Throwable;)V [ERROR] ----------------------------------------------------- [ERROR] realm = plugin>com.liferay.maven.plugins:liferay-maven-plugin:6.1.0 [ERROR] strategy = org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy [ERROR] urls[0] = file:/...../maven_repo/com/liferay/maven/plugins/liferay-maven-plugin/6.1.0/liferay-maven-plugin-6.1.0.jar [ERROR] urls[1] = file:/...../maven_repo/com/liferay/portal/portal-impl/6.1.0/portal-impl-6.1.0.jarSuspect this has something to do with different version of SLF4j that is not compatible with the one that maven resolved to when running liferay-maven-plugin, so went ahead and force the SLF4j version that the plugin was using to 1.5.5
...It seems to fix this issue, but now I'm bumped with another NullPointerException coming off liferay-maven-plugin source itself. Logged a defect with the Liferay team here (MAVEN-15). Will have to wait and see how this paints out. Liferay-maven-plugin turns out to be quite a pain in the neck for me ... :-( Guess I should be evaluating Liferay IDE instead to see if it suits me better. It does required that the whole plugins project to be under a Liferay-Plugin-SDK directory though.... ... com.liferay.maven.plugins liferay-maven-plugin ${liferay.version} ${liferay.auto.deploy.dir} ${liferay.version} portlet org.slf4j slf4j-log4j12 1.5.5
Monday, March 5, 2012
Liferay's Maven Archetypes
- liferay-ext-archetype
- liferay-hook-archetype
- liferay-layouttpl-archetype
- liferay-portlet-archetype
- liferay-theme-archetype
- liferay-web-archetype
liferay.version liferay.auto.deploy.dirthrough my profile settings in ~/.m2/settings.xml
with the mvn command to invoke them as follows... ... ...... liferay-plugins-development ... ...
mvn archetype:generate
-DarchetypeArtifactId=liferay-portlet-archetype
-DarchetypeGroupId=com.liferay.maven.archetypes
-DarchetypeVersion=6.1.0
-DarchetypeCatalog=local,remote
-DartifactId=sample-portlet
-DgroupId=com.liferay.sample
-Dversion=1.0-SNAPSHOT
and the following mvn command just to install the whatever resultant artifacts using the 'liferay-plugins-development' profile
mvn install -P liferay-plugins-development
Tuesday, February 28, 2012
Bash command that save my ass over and over again
find . -iname <some file name>To find files recursively
find . -iname <some file name> | xargsTo find files recursively and list them out horizontally separated by space and doing escaping when necessary
find . -iname <some file name> | xargs <some other bash commands>To find files recursively and list them out as arguments such that we could perform other commands on it like rm -f (force delete) for example
grep -ir 'some text' .Find all files recursively starting with the current directory We could do interesting stuff like
find . -iname '*.xml' | xargs grep -i "testing"Find all xml files recursively starting with current directory that has text 'testing' contains in it. Bash commands ROCKS! It's always worthwhile if you are using a windows machine to install Cygwin, it comes with bash by default so you could dig up code segment quickly rather than relying on the pathetic doggy search that comes with Windows. Just me 2 cents !