Here is a post from email thread about problems doing concurrent builds in hudson:
---
You may want to consider moving the build directory from
$HOME/.grails/... to something in the source tree. Then when Hudson
removes the workspace, the build tree goes with it. Simply pass in the
system property "grails.work.dir" with the path of the workspace.
extracted from http://www.nabble.com/Re%3A-Build-automation-problems-with-Hudon-and-1.0.3.---FIXED-to17818458.html#a17819003
Thursday, June 19, 2008
Wednesday, May 7, 2008
Grails servlet flow for web requests
There have been so many posts on the grails list with confusion on the order in which different things happen : filters, interceptors, hibernate session creation etc. when handling an http request. To answer all such questions, Erick from grails mailing list has kindly put together this sequence description:
[ comments picked from GrailsDispatcherServlet source ]
// Merge the handler and web request interceptors into a single
// array. Note that we start with the web request interceptors
// to ensure that the OpenSessionInViewInterceptor (which is a
// web request interceptor) is invoked before the user-defined
// filters (which are attached to a handler interceptor). This
// should ensure that the Hibernate session is in the proper
// state if and when users access the database within their
// filters.So the basic flow is
1. Servlet Filter before chain.doFilter() (Acegi runs here)
2. GrailsDispatcherServlet.doDispatch() starts
3. Spring MVC Interceptors preHandle() (OSIVI opens session)
4. Grails Filters before closure
5. Controller beforeInterceptor
6. Controller action
7. Controller afterInterceptor
8. Grails Filters after closure
9. Spring MVC Interceptors postHandle
10. View rendering
11. Grails Filters afterView closure
12. Spring MVC Interceptors afterCompletion() (OSIVI closes session)
13. Grails DispatcherServlet.doDispatch() ends
14. Servlet Filter after chain.doFilter() (Sitemesh runs here)
[ comments picked from GrailsDispatcherServlet source ]
// Merge the handler and web request interceptors into a single
// array. Note that we start with the web request interceptors
// to ensure that the OpenSessionInViewInterceptor (which is a
// web request interceptor) is invoked before the user-defined
// filters (which are attached to a handler interceptor). This
// should ensure that the Hibernate session is in the proper
// state if and when users access the database within their
// filters.So the basic flow is
1. Servlet Filter before chain.doFilter() (Acegi runs here)
2. GrailsDispatcherServlet.doDispatch() starts
3. Spring MVC Interceptors preHandle() (OSIVI opens session)
4. Grails Filters before closure
5. Controller beforeInterceptor
6. Controller action
7. Controller afterInterceptor
8. Grails Filters after closure
9. Spring MVC Interceptors postHandle
10. View rendering
11. Grails Filters afterView closure
12. Spring MVC Interceptors afterCompletion() (OSIVI closes session)
13. Grails DispatcherServlet.doDispatch() ends
14. Servlet Filter after chain.doFilter() (Sitemesh runs here)
Tuesday, April 29, 2008
How to add transactions to your grails business logic
There are 3 common ways in which you can surround your existing groovy or java code with transactions support under grails framework:
1. grails 'service' classes are transactional by default.
As long as the following statement is included in your grail service class, all methods executed will be executed under ongoing transaction. If no transaction exists when entering the service method, a new one will be auto created.
boolean transactional = true
2. If you are working with one or more grails domain objects in your code, wrap the code in 'withTransaction' block against one of the domain objects.
Described in more detail here:
http://grails.org/doc/1.0.x/guide/single.html#5.6%20Programmatic%20Transactions
3. Manually access hibernate session and create transaction against the session. This of course is tedious way and would require you to handle any exceptions yourself.
def session = sessionFactory.getCurrentSession()
Transaction tx = session.beginTransaction()
<>
tx.commit()
or
tx.rollback()
at the end.
4. Use spring declarative transaction control. I personally haven't tried it with grails; if you have please free feel to comment.
1. grails 'service' classes are transactional by default.
As long as the following statement is included in your grail service class, all methods executed will be executed under ongoing transaction. If no transaction exists when entering the service method, a new one will be auto created.
boolean transactional = true
2. If you are working with one or more grails domain objects in your code, wrap the code in 'withTransaction' block against one of the domain objects.
Described in more detail here:
http://grails.org/doc/1.0.x/guide/single.html#5.6%20Programmatic%20Transactions
3. Manually access hibernate session and create transaction against the session. This of course is tedious way and would require you to handle any exceptions yourself.
def session = sessionFactory.getCurrentSession()
Transaction tx = session.beginTransaction()
<>
tx.commit()
or
tx.rollback()
at the end.
4. Use spring declarative transaction control. I personally haven't tried it with grails; if you have please free feel to comment.
Saturday, April 12, 2008
grails continuous integration using hudson
Hudson is a powerful continuous integration environment for Windows / Linux systems. The big selling point of hudson is its simplicity compared to other popular integration systems as cruisecontrol: everything is done using the intuitive GUI with guidance on each step. No mucking around with xml files or shell commands to check system status ...
Described here are the steps you need to follow to automate the grails build, unit and regression testing environment using hudson continuous integration environment.
Prerequisites:
1. grails 1.0.1 or higher
2. jdk 1.5 or higher
3. hudson 1.2 onwards ( earlier versions may work as well, but we only tested hudson 1.2.x.x versions)
4. apache ant 1.6 onwards
5. apache tomcat 5.5 onwards (to run hudson inside servlet container)
6. Knowledge of grails and basic system admin; no expertise in hudson needed
Sample Continuous Integration Cycle:
Continous integration cycle of our example app performs the following steps:
a) Update the build system copy of application to latest source code from SCM
b) Run grails upgrade to create any missing files
c) Generate the application war file if needed
d) Run unit / integration tests
e) Run system functional tests
f) Generate application artifacts and reports for the above tests
g) Email/notify the admin in case there were problems with any of the above steps
System setup:
Follow the steps below in sequence to setup the environment on either UNIX or Windows machine:
Step1: Install
Download and install hudson.war into tomcat server webapps directory. If you are using app server different from tomcat, follow the app server specific instructions to install and bringup hudson.
Step 2: Update application files
(a) Modify build.xml:
Add the following to your default build.xml to enable ant based execution of 'grails upgrade' and grails 'run-webtest'
(b) Create Build script:
Even though hudson can directly execute ant commands, we will need to define our own build script to invoke ant. This allows us complete control our environment variables to be passed to grails. The control is especially useful in a hosted environment, where we do not have control over original environment (GRAILS_HOME, JAVA_HOME , PATH) etc passed to hudson.
The UNIX build script we will use is (to build grails project 'locate' , called buildlocate.sh):
# export env variables
JAVA_HOME=/usr/lib/jvm/java-6-sun-1.6.0.00;
export JAVA_HOME
GRAILS_HOME=/opt/grails
export GRAILS_HOME
# cd to project directory within hudson workspace:
cd locate
echo "classpath is $CLASSPATH; java home is $JAVA_HOME"
env
# remove JAVA_OPTS provided by hudson as it may cause errors
export -n JAVA_OPTS
export JAVA_OPTS=-Xmx768m
# now run the grails build / tests
exec ant upgrade war test webtest
Equivalent Windows script to use is (buildlocate.bat) :
REM set any global env vars in the beginning as necessary
set JAVA_HOME=C:\Program Files\jdk1.6.0_01
set GRAILS_HOME=C:\Programs\grails
REM cd to project directory within hudson workspace:
cd locate
REM reset JAVA_OPTS provided by hudson as it may cause errors
set JAVA_OPTS=-Xmx768m
# now run the grails build / tests
call ant upgrade war test webtest
Step 4: Hudson Configuration using Web Interface
Here are the steps you need to follow
1. Open the hudson dashboard on your browser
http://your_hudson_server_ip/hudson/
2. Select 'New job' option on hudson console,
3. On the new job page, give a name to your hudson project . We call it 'projectlocate'
Make sure you select "Build a free-style software project" , click OK to go to detailed configuration page.
4. Expand Advanced Project Options by clicking on the Advanced button:
The description below applies to source code management using subversion:
Select Subversion source code management system;
Repository URL: put the http URL of your subversion repository
e.g. http://127.0.0.1/svn/trunk/server/locate
Leave the repository browser option to Auto
hudson will immediately attempt to contact the svn repository; and will prompt you to 'enter credentials' if the access requires authentication.
You can provide multiple project locations to pull in components of your build environment as needed here. Our example here uses a single project location, checked out under subdirectory 'locate'
5. Define the right Build Triggers: the most common is to select 'build peridoically' option to do nightly builds. You can enter the schedule in UNIX crontab like format.
6. Click on 'Build -> Add build step' button:
Choose 'Execute shell' for UNIX , 'Execute Windows batch command for Windows'. As described before, 'Invoke ant' option cannot be used directly here due to the need to customize environment variables.
Provide the full path of the unix shell script or windows batch file under the command textbox.
e.g. /home/rahul/hudson/grailsbuildlocate.sh
This is the same UNIX build script we defined above.
7. Under Post-build Actions, check 'Archive the artifacts':
You can provide any of the artifacts or war files produced by the project.
e.g. our sample project produces locate.war that we can archive as result of successful build.
Also, add any artifacts you would like to have easy access to for information purposes.
We added locate/webtest/reports/WebTestResults.html; generated by running canoo webtest scripts.
8. Select 'Publish JUnit test result report' for any of your unit test reports that you want to be visible from hudson web console.
You can use wildcards to include all reports, hudson will automatically diff the successful tests across builds as they happen.
e.g. locate/test/reports/*.xml
9. Lastly, we add email notifications for the build admin email address.
Check 'E-mail notification' and define email address of recipient in the textbox.
Hudson Email Config:
For hudson to be able to send emails, you do need to configure email server details for the overall hudson application:
Go to hudson dashboard, select 'Manage Hudson' to update hudson global configuration. This can also be accessed by URL /hudson/manage
Select 'System Configuration' : 'E-mail Notification'
The example here describes use of gmail as email server:
SMTP server : smtp.gmail.com
Check 'Use SMTP authentication'
User Name: your gmail user name
Password: your gmail password
Check 'Use SSL'
Hudson enables you to do an instant email config test using the hyperlink: 'Test configuration by sending email to system admin address'
Other useful tips:
If you found the above useful, here are few more tips to keep in mind when setting up hudson projects for grails:
1. The above example did not add any security to hudson, a real life hudson based CI server must have a user login to do any build admin tasks. You can add security to hudson Enable security check, and specify Security Realm and authorization as needed.
2. In the example given, the project war file is created before running unit tests. This is important, because executing 'grails war' command after 'grails test-app' will force the cleanup of all unit test reports; in that case hudson will not find any unit test reports to archive.
3. For the case as in the example, the webtest plugin is included in the application. The webtest execution forces the bringup of application on the server port. To avoid clash with application server already running on your machine, ensure that you set webtest_port under webtest/conf/webtest.properties to a different value . e.g. if tomcat server on your build / test server already runs on port 8080, specify webtest_port as 9090 etc. to avoid the clash.
4. ant was used to build the above example, but it is not required. The build can also be executed fully under Windows batch command or UNIX shell script.
Here are UNIX bash shell script lines to replace the ant command:
# bash CI script:
function error {
echo ERROR
exit 1
}
trap error ERR
grails upgrade -force
grails war
grails test-app
grails run-webtest
The above ensures that the shell script exits as soon as any of the grails commands returns with non zero exit code. This is important to enable hudson to detect build failure at the right step and notify the build admin.
5. Manual debugging of the CI environment can be done on build machine by directly executing the build script under the build copy of the project. You can find the CI build copy created by hudson under:
UNIX: ~build_home/.hudson/jobs/hudson_project_name/workspace
Windows: file://documents and Settings/build_user/.hudson/jobs/hudson_project_name/workspace
--------
Appreciate any feedback / suggestions you folks may have on the process above.
Described here are the steps you need to follow to automate the grails build, unit and regression testing environment using hudson continuous integration environment.
Prerequisites:
1. grails 1.0.1 or higher
2. jdk 1.5 or higher
3. hudson 1.2 onwards ( earlier versions may work as well, but we only tested hudson 1.2.x.x versions)
4. apache ant 1.6 onwards
5. apache tomcat 5.5 onwards (to run hudson inside servlet container)
6. Knowledge of grails and basic system admin; no expertise in hudson needed
Sample Continuous Integration Cycle:
Continous integration cycle of our example app performs the following steps:
a) Update the build system copy of application to latest source code from SCM
b) Run grails upgrade to create any missing files
c) Generate the application war file if needed
d) Run unit / integration tests
e) Run system functional tests
f) Generate application artifacts and reports for the above tests
g) Email/notify the admin in case there were problems with any of the above steps
System setup:
Follow the steps below in sequence to setup the environment on either UNIX or Windows machine:
Step1: Install
Download and install hudson.war into tomcat server webapps directory. If you are using app server different from tomcat, follow the app server specific instructions to install and bringup hudson.
Step 2: Update application files
(a) Modify build.xml:
Add the following to your default build.xml to enable ant based execution of 'grails upgrade' and grails 'run-webtest'
(b) Create Build script:
Even though hudson can directly execute ant commands, we will need to define our own build script to invoke ant. This allows us complete control our environment variables to be passed to grails. The control is especially useful in a hosted environment, where we do not have control over original environment (GRAILS_HOME, JAVA_HOME , PATH) etc passed to hudson.
The UNIX build script we will use is (to build grails project 'locate' , called buildlocate.sh):
# export env variables
JAVA_HOME=/usr/lib/jvm/java-6-sun-1.6.0.00;
export JAVA_HOME
GRAILS_HOME=/opt/grails
export GRAILS_HOME
# cd to project directory within hudson workspace:
cd locate
echo "classpath is $CLASSPATH; java home is $JAVA_HOME"
env
# remove JAVA_OPTS provided by hudson as it may cause errors
export -n JAVA_OPTS
export JAVA_OPTS=-Xmx768m
# now run the grails build / tests
exec ant upgrade war test webtest
Equivalent Windows script to use is (buildlocate.bat) :
REM set any global env vars in the beginning as necessary
set JAVA_HOME=C:\Program Files\jdk1.6.0_01
set GRAILS_HOME=C:\Programs\grails
REM cd to project directory within hudson workspace:
cd locate
REM reset JAVA_OPTS provided by hudson as it may cause errors
set JAVA_OPTS=-Xmx768m
# now run the grails build / tests
call ant upgrade war test webtest
Step 4: Hudson Configuration using Web Interface
Here are the steps you need to follow
1. Open the hudson dashboard on your browser
http://your_hudson_server_ip/hudson/
2. Select 'New job' option on hudson console,
3. On the new job page, give a name to your hudson project . We call it 'projectlocate'
Make sure you select "Build a free-style software project" , click OK to go to detailed configuration page.
4. Expand Advanced Project Options by clicking on the Advanced button:
The description below applies to source code management using subversion:
Select Subversion source code management system;
Repository URL: put the http URL of your subversion repository
e.g. http://127.0.0.1/svn/trunk/server/locate
Leave the repository browser option to Auto
hudson will immediately attempt to contact the svn repository; and will prompt you to 'enter credentials' if the access requires authentication.
You can provide multiple project locations to pull in components of your build environment as needed here. Our example here uses a single project location, checked out under subdirectory 'locate'
5. Define the right Build Triggers: the most common is to select 'build peridoically' option to do nightly builds. You can enter the schedule in UNIX crontab like format.
6. Click on 'Build -> Add build step' button:
Choose 'Execute shell' for UNIX , 'Execute Windows batch command for Windows'. As described before, 'Invoke ant' option cannot be used directly here due to the need to customize environment variables.
Provide the full path of the unix shell script or windows batch file under the command textbox.
e.g. /home/rahul/hudson/grailsbuildlocate.sh
This is the same UNIX build script we defined above.
7. Under Post-build Actions, check 'Archive the artifacts':
You can provide any of the artifacts or war files produced by the project.
e.g. our sample project produces locate.war that we can archive as result of successful build.
Also, add any artifacts you would like to have easy access to for information purposes.
We added locate/webtest/reports/WebTestResults.html; generated by running canoo webtest scripts.
8. Select 'Publish JUnit test result report' for any of your unit test reports that you want to be visible from hudson web console.
You can use wildcards to include all reports, hudson will automatically diff the successful tests across builds as they happen.
e.g. locate/test/reports/*.xml
9. Lastly, we add email notifications for the build admin email address.
Check 'E-mail notification' and define email address of recipient in the textbox.
Hudson Email Config:
For hudson to be able to send emails, you do need to configure email server details for the overall hudson application:
Go to hudson dashboard, select 'Manage Hudson' to update hudson global configuration. This can also be accessed by URL /hudson/manage
Select 'System Configuration' : 'E-mail Notification'
The example here describes use of gmail as email server:
SMTP server : smtp.gmail.com
Check 'Use SMTP authentication'
User Name: your gmail user name
Password: your gmail password
Check 'Use SSL'
Hudson enables you to do an instant email config test using the hyperlink: 'Test configuration by sending email to system admin address'
Other useful tips:
If you found the above useful, here are few more tips to keep in mind when setting up hudson projects for grails:
1. The above example did not add any security to hudson, a real life hudson based CI server must have a user login to do any build admin tasks. You can add security to hudson Enable security check, and specify Security Realm and authorization as needed.
2. In the example given, the project war file is created before running unit tests. This is important, because executing 'grails war' command after 'grails test-app' will force the cleanup of all unit test reports; in that case hudson will not find any unit test reports to archive.
3. For the case as in the example, the webtest plugin is included in the application. The webtest execution forces the bringup of application on the server port. To avoid clash with application server already running on your machine, ensure that you set webtest_port under webtest/conf/webtest.properties to a different value . e.g. if tomcat server on your build / test server already runs on port 8080, specify webtest_port as 9090 etc. to avoid the clash.
4. ant was used to build the above example, but it is not required. The build can also be executed fully under Windows batch command or UNIX shell script.
Here are UNIX bash shell script lines to replace the ant command:
# bash CI script:
function error {
echo ERROR
exit 1
}
trap error ERR
grails upgrade -force
grails war
grails test-app
grails run-webtest
The above ensures that the shell script exits as soon as any of the grails commands returns with non zero exit code. This is important to enable hudson to detect build failure at the right step and notify the build admin.
5. Manual debugging of the CI environment can be done on build machine by directly executing the build script under the build copy of the project. You can find the CI build copy created by hudson under:
UNIX: ~build_home/.hudson/jobs/hudson_project_name/workspace
Windows: file://documents and Settings/build_user/.hudson/jobs/hudson_project_name/workspace
--------
Appreciate any feedback / suggestions you folks may have on the process above.
How to change the name of file to be downloaded..
Example from mailing list:
If I have a controller say:
def genFile {
ByteArrayOutputStream out = new ByteArrayOutputStream();
.... read data into outputstream here
response.setContentType('application/exe')
out.writeTo(response.getOutputStream())
out.close()
}
The file name presented to the user for save would be 'genFile'
However, adding the following in the beginning of controller would force the browser to recognize a different name:
response.addHeader("content-disposition", "attachment;filename=myfilename.ext")
If I have a controller say:
def genFile {
ByteArrayOutputStream out = new ByteArrayOutputStream();
.... read data into outputstream here
response.setContentType('application/exe')
out.writeTo(response.getOutputStream())
out.close()
}
The file name presented to the user for save would be 'genFile'
However, adding the following in the beginning of controller would force the browser to recognize a different name:
response.addHeader("content-disposition", "attachment;filename=myfilename.ext")
Friday, April 11, 2008
Making jsp files reloadable
The secret of jsp reloading described by Graeme:
under (http://archive.grails.codehaus.org/user/3f2c19a70804110109h66324f79s8cabb490b7b7e5f7@mail.gmail.com)
Basically you can edit the generation template of web.xml with the settings to enable reloading of jsp files.
Note that this will apply to all web.xml files generated for grails applications in your environment.
Also, will need to take care of modifying the webdefault.xml file when moving to a new release of grails !
Purpose of this blog
All,
I've been avidly following grails mailing list for quite a while. With heavy traffic on list, there are so many useful gems of wisdom that flow thru the list everyday; however my limited time to arrange them leaves me with lot of questions 'this was definitely answered in grails list, but how do I find the right question ?" etc...
This blog is attempt to manually get the useful items (at least once that I find useful ) from the list and put them in the list every day.
I've been avidly following grails mailing list for quite a while. With heavy traffic on list, there are so many useful gems of wisdom that flow thru the list everyday; however my limited time to arrange them leaves me with lot of questions 'this was definitely answered in grails list, but how do I find the right question ?" etc...
This blog is attempt to manually get the useful items (at least once that I find useful ) from the list and put them in the list every day.
Subscribe to:
Posts (Atom)