Although this tale is not about folder structure (most developers have it similar), we will start with one. This is how all my Liferay portal project folders look like:
I have several project folders organized similar to this one: for 5.2.x branch, for 6.0.x branch etc. Image shows folder that is dedicated for the trunk. (I obviously love to assign icons to folders for better visual overview;).
This tale will uncover some tricks I am using frequently. Once again, its me who finds these tips useful; its on you to evaluate and decide for yourself:)
Enough of small talk, lets go to the point. There are two things with this structure I would love to share:
1 - Runner to run 'clean' java code without ant and container
2 - Invoke common commands with ease using Launchy
*This tip is mostly for IntelliJ users*
Portal implementaion and definition is split in two modules: portal-impl and portal-services. At the module level, portal-impl module has a 'provided' dependency of portal-service (IntelliJ users will recognize this term:). Meaning: dependency is available in compile time, but not in runtime. This is because portal-service is not deployed with the web application.
When coding some implementation, it would be very cool if we can run it without the container, so we can test and debug it! Due to provided dependency, portal services are not available on running classpath. So, the following code placed in simple Java class with main() method will not run:
Its because portal-service output (jar, classes) is not on classpath when snippet is run.
Therefore, i added another top-level Java module named 'runner'. It is local only, out of SVN. I've made this module depend (with scope 'compile') on portal-impl and portal-service, so both are available on the classpath in compile and run time. Now I am able to run the following code:
new ServiceUtil().setService(new ServiceImpl());
Of course, the running code has to be servlets-api-free, but in most of cases you have some logic layers that are decoupled from the servlets-api.
takeaway: use services and impl code without the ant and container - the code-test-fix cycle is much shorter;)
Launchy is Quicksilver clone for Windows. It may launch files, programs etc with just few keystrokes. Yeah, now you see why all those *.bat files in the root are for:) But problem is that I have several project folders (trunk, v6.0, v5.2...) and the batch file names are the same in all of them. Here comes PyLaunchy and PyDiry plugins to the rescue.
These plugins allow user to assign Launchy shortcut to any folder and to launch directory content. So, for example, I am using following shortcut names:
- ll for /liferay
- l60 for /liferay-6.0-ee
- l52 for /liferay-5.2
etc. That makes me able to invoke any defined batch command on project of my choice. Here is it in action:
Launchy is clever so you do not have to type the complete name:
And there is zero maintenance - just add a new batch for your common work and it will appear in the Launchy list. For a new project, simply copy batches you need to it's root.
For me, this is a faster (only few keystrokes) and more convenient (don't have to navigate to the exact folder, don't have to have IDE on) way to invoke common commands. I use it everyday. Let me give you another example: while i am coding something on trunk, I can invoke SVN update and then ant all and then wlogic deploy on portal 5.2 project, since I know I have to fix some issue there later today. Once when all is done, I can stop with what i was working and switch to the 5.2 project and everything will be ready.
But wait, there is another little trick;) If you are like me, then you hate waiting for ant-deploy or ant-all to finish:) I always try to look at some code while portal is being builded/deployed... and often forgot to continue back when ant finishes its job, ha:) Therefore, for all lengthy batch jobs, I've added little Hotkey notification that gives me a visual and sound information that batch finished with its job:
takeaway: run predefined common operations on desired project with just few keystrokes.