Icescrum setup on Debian Squeeze

As official Icescrum documentation is too short for a non Java expert to setup this product on a Debian system, this page details required tricks and also propose advice for a production environment.

Do not (re)start Tomcat before having raised the point where I tell you can start it.

Packages

First, required Debian packages (and dependencies) to install with aptitude or apt-get:
sun-java6-bin
sun-java6-jre
sun-java6-fonts
tomcat6
mysql-server

I do not recommend the use of openjdk-6 packages.

Database

Create your MySQL database and user for icescrum:
$ mysql -u root -p
mysql> create database icescrum character set utf8;
Query OK, 1 row affected (0.00 sec)

mysql> grant all privileges on icescrum.* to 'icescrum'@'localhost' identified by 'icescrumpswd';
Query OK, 0 rows affected (0.00 sec)

Of course, please use complex root and icescrum MySQL passwords.

Application

Download the icescrum_R4.x_WAR.zip file and extract it to get the WAR file itself, which is a zip file too after all. I decided to place it in /opt.

cd /tmp
unzip icescrum_R4_3.1_war.zip
mv icescrum.war /opt/icescrum-4.3.1.war
ln -s /opt/icescrum-4.3.1.war /opt/icescrum.war
chmod g+r-wx,o-rwx /opt/icescrum-4.3.1.war

Application work files

Icescrum is built with Grails and LiquidBase which both write files – I consider as temporary files. By default, it also stores users’ avatars and its application log icescrum.log in the current Java process working directory. The following command prepares a directory to get all that stuff but divert logs files to relevant location.

mkdir -p /var/local/icescrum/lbdsl
chown -R tomcat6.tomcat6 /var/local/icescrum
ln -s /var/log/tomcat6 /var/local/icescrum/logs

Application configuration

Extract the template configuration file with the following commands

cd /tmp
unzip /opt/icescrum.war WEB-INF/classes/config.properties
mv WEB-INF/classes/config.properties /etc/tomcat6/icescrum-config.properties

Edit that file with your database settings, MTA information – I suppose you have a satellite available on localhost – and browser’s URL required by Grails:

dataSource.driverClassName=org.gjt.mm.mysql.Driver
dataSource.dialect=org.hibernate.dialect.MySQLInnoDBDialect
dataSource.url=jdbc:mysql://localhost:3306/icescrum?useUnicode=true&characterEncoding=utf8&autoReconnect=true
dataSource.username=icescrum
dataSource.password=icescrumpswd
dataSource.dbCreate=update

grails.mail.host = localhost
grails.mail.port = 25
grails.mail.username = icescrum@localhost
grails.mail.password =

grails.serverURL=http://localhost:8080/icescrum

Tomcat configuration

Create a Tomcat context file at location /etc/tomcat6/Catalina/localhost/icescrum.xml with the content:

<Context
path="/icescrum"
docBase="/opt/icescrum.war"
debug="0"
reloadable="false"
unpackWAR="true"
swallowOutput="true"
/>

Edit /etc/default/tomcat6 to set various parameters on Java command line:

JAVA_HOME=/usr/lib/jvm/java-6-sun

JAVA_OPTS="-Djava.awt.headless=true -XX:MaxPermSize=256m -Xmx512m -XX:+UseConcMarkSweepGC"
JAVA_OPTS="$JAVA_OPTS -Dicescrum_config_location=/etc/tomcat6/icescrum-config.properties"
JAVA_OPTS="$JAVA_OPTS -Dlbdsl.home=/var/local/icescrum/lbdsl/"
JAVA_OPTS="$JAVA_OPTS -Duser.home=/var/local/icescrum/"

Notice I had to disassemble liquibase/dsl/properties/LbdslProperties.class to discover the lbdsl.home property which enables to avoid the default location to /usr/share/tomcat6/.lbdsl !

Now you can restart Tomcat, wait for a while looking at /var/log/tomcat6/catalina.out and then connect to http://localhost:8080/icescrum/

But then change grails.serverURL in /etc/tomcat6/icescrum-config.properties to match your definite users’ URL access.

HTTPS configuration

Until I add more details to this section, please refer to http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html

I recommend to place the server key store in /etc/tomcat6/

Adapt grails.serverURL for https now and restart Tomcat.

Network configuration

To keep Tomcat running as standard user without changing ports to standard privileged 80 and/or 443, here are two iptables rules:

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-ports 8443

Please refer to http://wiki.debian.org/iptables to persist them in your Debian system.

Conclusion

This setup is designed for a productive environment. The original application release is kept unmodified to ease upgrades and all settings are placed in Unix standard locations.

There are still many details you may need to tune Icescrum for your specific platform, like memory settings (-Xmx in JAVA_OPTS) and database pooling. But this document is written as a start point. Do not hesitate to post comments if anything is unclear, wrong or requires improvements.

3 commentaires

  1. Yves,

    D’abord, merci beaucoup pour ce document et le temps passé aux tests et à sa rédaction.
    Il est très instructif pour un débutant sur Tomcat.

    Je viens de faire une installation de icescrum 4#4 sur une toute fraîche Debian Squeeze 64 bits minimaliste installée dans une VM.

    J’ai suivi pas à pas les étapes décrites dans ton document, comme pour le valider.

    Coté administration Debian, j’ai ajouté « non-free » à /etc/apt/sources-list pour pouvoir installer les paquets java sun.

    La seule chose que j’ai faite par rapport à ton document, c’est un

    - chgrp tomcat6 /opt/icescrum-4.4.war »

    pour permettre à tomcat6 de lire et déployer icescrum, les logs de tomcat6 remontant l’erreur suivante – je ne garde que le message important de la stack trace :

    java.lang.IllegalArgumentException: Fichier WAR invalide ou illisible : /opt/icescrum.war

    Donc en résumé : excellent guide line.

    Un grand merci à toi :)

  2. Bonjour,

    J’ai suivi cette procédure pour installer icescrum 5.1.2 .

    mais j’obtient cette erreur que je n’arrive pas à résoudre vu mon manque de maitrise de ces technologies, dans les logs icescrum.log au démarrage de tomcat :

    2012-07-29 01:30:18,945 [main] INFO grails.spring.BeanBuilder – [RuntimeConfiguration] Configuring data source for environment: PRODUCTION
    2012-07-29 01:30:29,906 [main] ERROR org.springframework.web.context.ContextLoader – Context initialization failed
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘messageSource’: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘transactionManager’: Cannot resolve reference to bean ‘sessionFactory’ while setting bean property ‘sessionFactory’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘sessionFactory’: Cannot resolve reference to bean ‘lobHandlerDetector’ while setting bean property ‘lobHandler’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘lobHandlerDetector’: Invocation of init method failed; nested exception is org.springframework.jdbc.support.MetaDataAccessException: Error while extracting DatabaseMetaData; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
    at org.codehaus.groovy.grails.commons.spring.ReloadAwareAutowireCapableBeanFactory.doCreateBean(ReloadAwareAutowireCapableBeanFactory.java:135)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.context.support.AbstractApplicationContext.initMessageSource(AbstractApplicationContext.java:755)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:413)
    at org.codehaus.groovy.grails.commons.spring.DefaultRuntimeSpringConfiguration.getApplicationContext(DefaultRuntimeSpringConfiguration.java:154)
    at org.codehaus.groovy.grails.commons.spring.GrailsRuntimeConfigurator.configure(GrailsRuntimeConfigurator.java:164)
    at org.codehaus.groovy.grails.commons.spring.GrailsRuntimeConfigurator.configure(GrailsRuntimeConfigurator.java:124)
    at org.codehaus.groovy.grails.web.context.GrailsConfigUtils.configureWebApplicationContext(GrailsConfigUtils.java:120)
    at org.codehaus.groovy.grails.web.context.GrailsContextLoader.createWebApplicationContext(GrailsContextLoader.java:73)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:197)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4206)
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4705)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:799)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:779)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:601)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:675)
    at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:601)
    at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:502)
    at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1317)
    at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:324)
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:142)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1065)
    at org.apache.catalina.core.StandardHost.start(StandardHost.java:840)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1057)
    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:463)
    at org.apache.catalina.core.StandardService.start(StandardService.java:525)
    at org.apache.catalina.core.StandardServer.start(StandardServer.java:754)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:595)
    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:597)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘transactionManager’: Cannot resolve reference to bean ‘sessionFactory’ while setting bean property ‘sessionFactory’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘sessionFactory’: Cannot resolve reference to bean ‘lobHandlerDetector’ while setting bean property ‘lobHandler’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘lobHandlerDetector’: Invocation of init method failed; nested exception is org.springframework.jdbc.support.MetaDataAccessException: Error while extracting DatabaseMetaData; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1325)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1086)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.codehaus.groovy.grails.commons.spring.ReloadAwareAutowireCapableBeanFactory.doCreateBean(ReloadAwareAutowireCapableBeanFactory.java:135)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
    at org.codehaus.groovy.grails.orm.support.TransactionManagerPostProcessor.postProcessAfterInstantiation(TransactionManagerPostProcessor.java:77)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1036)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
    … 39 more
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘sessionFactory’: Cannot resolve reference to bean ‘lobHandlerDetector’ while setting bean property ‘lobHandler’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘lobHandlerDetector’: Invocation of init method failed; nested exception is org.springframework.jdbc.support.MetaDataAccessException: Error while extracting DatabaseMetaData; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1325)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1086)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.codehaus.groovy.grails.commons.spring.ReloadAwareAutowireCapableBeanFactory.doCreateBean(ReloadAwareAutowireCapableBeanFactory.java:135)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:322)
    … 52 more
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘lobHandlerDetector’: Invocation of init method failed; nested exception is org.springframework.jdbc.support.MetaDataAccessException: Error while extracting DatabaseMetaData; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1420)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    at org.codehaus.groovy.grails.commons.spring.ReloadAwareAutowireCapableBeanFactory.doCreateBean(ReloadAwareAutowireCapableBeanFactory.java:135)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:322)
    … 63 more
    Caused by: org.springframework.jdbc.support.MetaDataAccessException: Error while extracting DatabaseMetaData; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.
    at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:296)
    at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:320)
    at org.codehaus.groovy.grails.orm.hibernate.support.SpringLobHandlerDetectorFactoryBean.afterPropertiesSet(SpringLobHandlerDetectorFactoryBean.java:72)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)
    … 71 more
    Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.Util.getInstance(Util.java:386)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1013)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:982)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927)
    at com.mysql.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:2237)
    at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2158)
    at com.mysql.jdbc.ConnectionImpl.(ConnectionImpl.java:792)
    at com.mysql.jdbc.JDBC4Connection.(JDBC4Connection.java:47)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:381)
    at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:305)
    at $Proxy20.getMetaData(Unknown Source)
    Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Access denied for user ‘icescrum’@'localhost’ to database ‘projet’
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.Util.getInstance(Util.java:386)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1052)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3609)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3541)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:943)
    at com.mysql.jdbc.MysqlIO.secureAuth411(MysqlIO.java:4113)
    at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1308)
    at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2336)
    at com.mysql.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:2176)
    … 7 more

    • Bonjour, d’après le message d’erreur MySQLSyntaxErrorException: Access denied for user ‘icescrum’@’localhost’ to database ‘projet’ il s’agit d’un problème de permission du compte icescrum dans MySQL. Probablement que vous avez manqué la commande grant all privileges … ou bien vous n’avez pas adapté convenablement la commande au nom de base de données projet que vous avez choisi.

Laisser un commentaire