To be able to view Javadoc for classes packaged in Maven dependencies in Eclipse, go to the Java Resources -> Libraries -> Maven Dependencies in the project and right click on one of the dependencies listed. From the ‘Maven’ menu option choose ‘Download Sources’ and both source and Javadoc will be downloaded. Note that choosing the ‘Javadoc’ option didn’t seem to download the Javadoc!
November 6, 2010
October 14, 2010
Hibernate 3, Spring Framework 3, MySQL and Maven 2
To add database connectivity to the siark.com webapp I’m using a MySQL database To add database connectivity to the siark.com webapp I’m using a MySQL database and the Hibernate ORM framework. I need to add some dependencies to my pom.xml, some of which (Hibernate) are not in any of the repositories supported by Nexus in it’s out-of-the-box state. The Hibernate jar files are available from the JBoss repository.
To add a new proxy repository to Nexus.
1 Log in to Nexus as an admin.
2 Select ‘Proxy Repository’ from the ‘Add’… menu.
3 Enter the ‘Repository ID’ ‘jboss’, ‘Repository Name’ ‘JBoss Repository’, ‘Remote Storage Location’ ‘http://repository.jboss.org/nexus/content/groups/public’ and press the ‘Save’ button.
4 Select the ‘Public Repositories’ from the repository list. Select the ‘JBoss Repository’ from the ‘Available Repositories’ list and add it to the ‘Ordered Group Repositories’ list. Press the ‘Save’ button.
I can now add Hibernate to my pom.xml.
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>3.5.6-Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-annotations</artifactId> <version>3.5.6-Final</version> </dependency>
For some reason it’s also necessary to add javassist to the pom.xml (A Hibernate dependency that isn’t included in the dependencies!)
<dependency> <groupId>javassist</groupId> <artifactId>javassist</artifactId> <version>3.11.0.GA</version> </dependency>
and slf4j (See http://www.slf4j.org/codes.html#StaticLoggerBinder for more options with slf4j.)
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.5.8</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.5.8</version> </dependency>
As many of the annotations used in the Hibernate POJO’s are java persistence annotations, it’s necessary to add persistence-api to the pom.xml.
<dependency> <groupId>javax.persistence</groupId> <artifactId>persistence-api</artifactId> <version>1.0</version> </dependency>
As I’m using Spring I also need to add spring-orm.
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${org.springframework.version}</version> </dependency>
Now I need to configure Spring to use MySQL and Hibernate.
I’ve decided to move my Spring MVC configuration into a file called mvc-config.xml and my Spring database configuraion in db-config.xml. Both of these files are referenced from the igallery-servlet.xml file (see https://siark.wordpress.com/2010/09/29/web-mvc-project-using-spring-framework-3-eclipse-helios-and-maven-2-on-os-x-snow-leopard/). All three of these files are located in the WEB-INF directory.
igallery-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- Scans the classpath of this application for @Components (@Service, @Controller, etc...) annotations to deploy as beans --> <context:component-scan base-package="com.siark.igallery" /> <!-- Configures Spring MVC --> <import resource="mvc-config.xml" /> <!-- Configures Hibernate - Database Config --> <import resource="db-config.xml" /> </beans>
mvc-config.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <!-- Configures the @Controller programming model --> <mvc:annotation-driven /> <!-- Resolves view names to protected .jsp resources within the /WEB-INF/jsp directory --> <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> </beans>
db-config.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:jdbc.properties</value> <value>classpath:igallery.properties</value> </list> </property> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"> <value>${jdbc.driverClassName}</value> </property> <property name="url"> <value>${jdbc.url}</value> </property> <property name="username"> <value>${jdbc.username}</value> </property> <property name="password"> <value>${jdbc.password}</value> </property> </bean> <!-- Hibernate SessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource"><ref local="dataSource" /></property> <property name="packagesToScan" value="com.siark.igallery.domain" /> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.show_sql">false</prop> </props> </property> </bean> <!-- Transaction manager for a Hibernate SessionFactory --> <tx:annotation-driven /> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory"> <ref local="sessionFactory" /> </property> </bean> </beans>
Finally my database properties are in a file called jdbc.properties which is in the src/main/resources directory but will end up in the WEB-INF/classes directory when the jar is packaged.
jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost/siark jdbc.username=username jdbc.password=password
October 5, 2010
October 1, 2010
Behaviour Driven Development With JBehave Web 3, Selenium and Maven 2 on OS X Snow Leopard
For integration testing on the siark.com webapp I’m using JBehave 3 and Selenium. As an initial test all I’m going to do is test that the home page displays the message “Welcome to the siark.com website.” when a user navigates to /igallery, the root of the siark.com website.I’m using the Page Object pattern to construct the tests.
1 Write a scenario and save it in a file called home.story in src/test/resources/com/siark/igallery/stories
Scenario: User opens home page Given the user opens the home page Then the home page should be displayed
2 Create a generic page class that I call IGalleryPage. The java file is created in src/test/java/com/siark/igallery.
package com.siark.igallery.pages; import org.jbehave.web.selenium.SeleniumPage; import com.thoughtworks.selenium.Selenium; import com.thoughtworks.selenium.condition.ConditionRunner; public class IGalleryPage extends SeleniumPage { public IGalleryPage(Selenium selenium, ConditionRunner conditionRunner) { super(selenium, conditionRunner); } }
3 Create a HomePage class that deals with the home page specifically. The java file is created in src/test/java/com/siark/igallery/pages.
package com.siark.igallery.pages; import com.thoughtworks.selenium.Selenium; import com.thoughtworks.selenium.condition.ConditionRunner; public class HomePage extends IGalleryPage { public HomePage(Selenium selenium, ConditionRunner conditionRunner) { super(selenium, conditionRunner); } public void open() { open("/igallery/"); } public void verifyPage() { textIsVisible("Welcome to the siark.com website."); } }
4 Now create a class called IGallerySteps that defines the annotations used in the story. The java file is created in src/test/java/com/siark/igallery.
package com.siark.igallery; import org.jbehave.core.annotations.Given; import org.jbehave.core.annotations.Then; import com.siark.igallery.pages.FindSteps; import com.siark.igallery.pages.HomePage; import com.siark.igallery.pages.PageFactory; public class IGallerySteps { private final PageFactory pageFactory; private HomePage home; public IGallerySteps(PageFactory pageFactory) { this.pageFactory = pageFactory; } @Given("the user opens the home page") public void theUserOpensTheHomePage() { home = pageFactory.home(); home.open(); } @Then("the home page should be displayed") public void theHomePageShouldBeDisplayed(){ home.verifyPage(); } }
5 A factory class called PageFactory is used to get page classes. The java class is created in src/test/java/com/siark/igallery/pages.
package com.siark.igallery.pages; import com.thoughtworks.selenium.Selenium; import com.thoughtworks.selenium.condition.ConditionRunner; public class PageFactory { private final Selenium selenium; private final ConditionRunner conditionRunner; public PageFactory(Selenium selenium, ConditionRunner conditionRunner) { this.selenium = selenium; this.conditionRunner = conditionRunner; } public HomePage home() { return new HomePage(selenium, conditionRunner); } }
6 To configure and run the tests, an embedable runnable class is created, which I have called IGalleryStories. The java file is created in src/test/java/com/siark/igallery.
package com.siark.igallery; import static java.util.Arrays.asList; import static org.jbehave.core.io.CodeLocations.codeLocationFromClass; import static org.jbehave.core.reporters.StoryReporterBuilder.Format.CONSOLE; import static org.jbehave.core.reporters.StoryReporterBuilder.Format.HTML; import static org.jbehave.core.reporters.StoryReporterBuilder.Format.TXT; import static org.jbehave.core.reporters.StoryReporterBuilder.Format.XML; import java.util.List; import org.jbehave.core.Embeddable; import org.jbehave.core.configuration.Configuration; import org.jbehave.core.io.CodeLocations; import org.jbehave.core.io.LoadFromClasspath; import org.jbehave.core.io.StoryFinder; import org.jbehave.core.junit.JUnitStories; import org.jbehave.core.reporters.ConsoleOutput; import org.jbehave.core.reporters.StoryReporter; import org.jbehave.core.reporters.StoryReporterBuilder; import org.jbehave.core.steps.CandidateSteps; import org.jbehave.core.steps.InstanceStepsFactory; import org.jbehave.core.steps.SilentStepMonitor; import org.jbehave.web.selenium.SeleniumConfiguration; import org.jbehave.web.selenium.SeleniumContext; import org.jbehave.web.selenium.SeleniumStepMonitor; import com.siark.igallery.pages.PageFactory; import com.thoughtworks.selenium.Selenium; import com.thoughtworks.selenium.condition.ConditionRunner; public class IGalleryStories extends JUnitStories { private Selenium selenium = SeleniumConfiguration.defaultSelenium(); private ConditionRunner conditionRunner = SeleniumConfiguration.defaultConditionRunner(selenium); private PageFactory pageFactory = new PageFactory(selenium, conditionRunner); private SeleniumContext seleniumContext = new SeleniumContext(); @Override public Configuration configuration() { Class<? extends Embeddable> embeddableClass = this.getClass(); return new SeleniumConfiguration() .useSelenium(selenium) .useSeleniumContext(seleniumContext) .useStepMonitor(new SeleniumStepMonitor(selenium, seleniumContext, new SilentStepMonitor())) .useStoryLoader(new LoadFromClasspath(embeddableClass)) .useStoryReporterBuilder(new StoryReporterBuilder() { @Override public StoryReporter reporterFor(String storyPath, Format format) { if (format == CONSOLE) { return new ConsoleOutput() { @Override public void beforeScenario(String title) { seleniumContext.setCurrentScenario(title); super.beforeScenario(title); } }; } else { return super.reporterFor(storyPath, format); } } } .withCodeLocation(CodeLocations.codeLocationFromClass(embeddableClass)) .withDefaultFormats() .withFormats(CONSOLE, TXT, HTML, XML)); } @Override public List<CandidateSteps> candidateSteps() { return new InstanceStepsFactory(configuration(), new IGallerySteps(pageFactory), new FailingScenarioScreenshotCapture(selenium)) .createCandidateSteps(); } @Override protected List<String> storyPaths() { return new StoryFinder().findPaths(codeLocationFromClass(this.getClass()).getFile(), asList("**/*.story"), null); } }
This class is actually the same class provided on the JBehave website 🙂
7 The last class is also from the JBehave website and is the FailingScenarioScreenshotCapture used in IGalleryStories. It is also created in src/test/java/com/siark/igallery.
package com.siark.igallery; import org.jbehave.core.annotations.AfterScenario; import org.jbehave.core.annotations.AfterScenario.Outcome; import org.jbehave.web.selenium.PerScenarioSeleniumSteps; import com.thoughtworks.selenium.Selenium; public class FailingScenarioScreenshotCapture extends PerScenarioSeleniumSteps { public FailingScenarioScreenshotCapture(Selenium selenium) { super(selenium); } @AfterScenario(uponOutcome = Outcome.FAILURE) public void afterFailingScenario() throws Exception { String home = System.getenv("HOME"); selenium.captureScreenshot(home+"/failedScenario.png"); } }
8 Finally I need to add a dependency for jbehave-web-selenium, the maven-jetty-plugin plugin so that the Jetty application server can be started and stopped and the igallery.war file can be deployed to it, the selenium-maven-plugin plugin to start and stop the Selenium server and lastly the jbehave-maven-plugin plugin to run the integration tests. The Jetty server will listen on port 8080 for HTTP requests, and the Selenium server will listen on port 4444.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.siark.igallery</groupId> <artifactId>igallery</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>Siark iGallery Webapp</name> <url>http://www.siark.com</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>org.jbehave.web</groupId> <artifactId>jbehave-web-selenium</artifactId> <version>3.0</version> <scope>test</scope> </dependency> </dependencies> <build> <finalName>igallery</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.5</source> <target>1.5</target> </configuration> </plugin> <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>maven-jetty-plugin</artifactId> <configuration> <webApp>${project.build.directory}/igallery.war</webApp> <webAppConfig> <contextPath>/igallery</contextPath> </webAppConfig> </configuration> <executions> <execution> <id>start-jetty</id> <phase>pre-integration-test</phase> <goals> <goal>run-war</goal> </goals> <configuration> <scanIntervalSeconds>0</scanIntervalSeconds> <daemon>true</daemon> </configuration> </execution> <execution> <id>stop-jetty</id> <phase>post-integration-test</phase> <goals> <goal>stop</goal> </goals> <configuration> <stopKey>stopJetty</stopKey> <stopPort>9966</stopPort> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>selenium-maven-plugin</artifactId> <version>1.0.1</version> <executions> <execution> <id>start-selenium</id> <phase>pre-integration-test</phase> <goals> <goal>start-server</goal> </goals> <configuration> <background>true</background> <debug>false</debug> <logOutput>true</logOutput> </configuration> </execution> <execution> <id>stop-selenium</id> <phase>post-integration-test</phase> <goals> <goal>stop-server</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.jbehave</groupId> <artifactId>jbehave-maven-plugin</artifactId> <version>3.0</version> <executions> <execution> <id>run-stories</id> <phase>integration-test</phase> <configuration> <includes> <include>**/*Stories.java</include> </includes> <scope>test</scope> </configuration> <goals> <goal>run-stories-as-embeddables</goal> </goals> </execution> </executions> <dependencies> <dependency> <groupId>org.jbehave.web</groupId> <artifactId>jbehave-web-selenium</artifactId> <version>3.0</version> </dependency> </dependencies> </plugin> </plugins> </build> <properties> <org.springframework.version>3.0.4.RELEASE</org.springframework.version> </properties> </project>
September 29, 2010
Web MVC Project using Spring Framework 3 Eclipse Helios and Maven 2 on OS X Snow Leopard
I want to create the simplest of webapps using Spring Framework 3 and JSP documents. The version of JSP is 2.1 as that is the version used by Tomcat 6.
1 Update the pom.xml with the Spring Framework dependencies.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.siark.igallery</groupId> <artifactId>igallery</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>Siark iGallery Webapp</name> <url>http://www.siark.com</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> </dependencies> <build> <finalName>igallery</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.5</source> <target>1.5</target> </configuration> </plugin> </plugins> </build> <properties> <org.springframework.version>3.0.4.RELEASE</org.springframework.version> </properties> </project>
2 Update the web.xml file to include the Spring Framework Dispatcher Servlet.
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <display-name>igallery</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>igallery</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>igallery</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping> </web-app>
The Dispatcher Servlet handles requests to all resources that have the extension html. The DispatcherServlet class is in the spring-webmvc artifact.
3 I want the JSP pages to be in the WEB-INF/jsp directory. As this directory is not part of the public hierarchy, the welcome page (index.jsp) must redirect to the home page (home.html) which is then intercepted by the Spring Framework Dispatcher servlet.
<?xml version="1.0" encoding="ISO-8859-1" ?> <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" info="siark.com home page" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> <title>siark.com home</title> </head> <body> <%-- Redirected because we can't set the welcome page to a virtual URL. --%> <c:redirect url="home.html" /> </body> </html>
4 The Spring Framework Web MVC uses a special file to configure it’s web application context and is based on the servlet name assigned to the dispatcher servlet (igallery). This file then is igallery-servlet.xml and by default is in the WEB-INF directory.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package="com.siark.igallery" /> <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jspx"/> </bean> </beans>
This minimal web application context configuration file includes an entry to enable auto-detection of annotated controllers and an entry to configure the view resolver.
5 The controller for the home page is as simple as possible and just handles an HTTP GET request.
package com.siark.igallery.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @Controller @RequestMapping("/home") public class HomeController { protected final Log logger = LogFactory.getLog(getClass()); /** * */ @RequestMapping(method=RequestMethod.GET) public void get() { logger.info("Returning the home view."); } }
The Controller annotation is in the spring-context artifact and the RequestMapping and RequestMethod annotations are in the spring-web artifact.
6 The home page itself is home.jspx and is in the WEB-INF/jsp directory. It is a JSP document.
<?xml version="1.0" encoding="ISO-8859-1" ?> <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:fmt="http://java.sun.com/jsp/jstl/fmt" version="2.0"> <jsp:directive.page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" /> <!-- According to the W3C XHTML 1.0 Recommendation, an XML declaration is not required, but authors are strongly encouraged to use XML declarations in documents. --> <jsp:text> <![CDATA[ <?xml version="1.0" encoding="ISO-8859-1" ?> ]]> </jsp:text> <!-- According to the W3C XHTML 1.0 Recommendation, there must be a DOCTYPE declaration prior to the root element. --> <jsp:text> <![CDATA[ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> ]]> </jsp:text> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> </head> <body> <p>Welcome to the siark.com website.</p> </body> </html> </jsp:root>
September 20, 2010
Installing Hudson CI on OS X Snow Leopard and Configuring it to use Subversion, Maven 2 and Nexus
1 Download the hudson.war file.
2 Create a HUDSON_HOME directory. As I did with Nexus, I am creating this in the Tomcat home directory. Create the .m2 directory for maven and copy the settings.xml that configures Maven 2 to use Nexus.
$ cd /Library/Tomcat/Home
$ mkdir .hudson
$ cd .hudson
$ mkdir .m2
$ cp ~/.m2/settings.xml .
$ sudo chown tomcat settings.xml
3 Edit the Tomcat5.sh script used to start Tomcat and add a HUDSON_HOME environment variable.
$ cd bin
$ sudo vi Tomcat5.sh
...
CATALINA_OPTS="-DHUDSON_HOME=$CATALINA_HOME/.hudson/ -Xmx512m -Djava.awt.headless=true"
...
4 Stop and restart Tomcat.
$ sudo ./Tomcat5.sh stop
$ sudo ./Tomcat5.sh start
5 Deploy the hudson.war using the Tomcat Web Application Manager. To do this navigate to http://localhost:8080/manager, and half way down the page is the Deploy section with a WAR file to deploy subsection. Press the Choose File button to choose the hudson.war file. then press the Deploy button to deploy it.
6 Navigate to http://localhost:8080/hudson to check the installation worked.
7 On the Hudson home page click the ‘New Job’ link. Add the job name igallery and choose the ‘Build a maven 2 project’ radio button. Click the ‘OK’ button.
8 On the next page, choose the ‘Subversion’ radio button under the ‘Source Code Management’ section. Add ‘http://localhost/svn/repos’ in the ‘Modules Repository URL’. You will need to enter the username and password setup for Subversion. Uncheck the ‘Use update’ checkbox and check the ‘Revert’ checkbox. In the ‘Build Triggers’ section check the ‘Poll SCM’ checkbox and choose a schedule. In the ‘Build’ section click the ‘system configuration’ link for the Maven Version. On the Hudson configuration page uncheck the tick box ‘Install automatically’ in the ‘Maven’ section and add ‘/usr/share/maven’ to ‘MAVEN_HOME’. Add a name for this maven installation. In the ‘Global properties’ section tick the ‘Environment variables’ checkbox and add the environment variable ‘HOME’ and give it the value ‘/Library/Tomcat/Home/.hudson’.
9 Back on the igallery job configuration page add ‘package’ to the ‘Goals and Options’ of the ‘Build’ section. Click the ‘Save’ button.
September 16, 2010
Creating a Simple Maven 2 Webapp in Eclipse
1 The first component to create is the pom.xml file. An easy way to generate a simple pom.xml file is to use the Maven 2 Archetype plugin to generate a basic Maven 2 project. By default the plugin operates in interactive, so a sequence of questions must be answered to generate the project (This Maven 2 plugin could have been used to generate the original iGallery project that was committed to Subversion in the post Configuring Subversion with Apache on OS X Snow Leopard).
$ cd ~/Development
$ mvn archetype:generate
Choose archetype:
...
82: remote -> maven-archetype-webapp (An archetype which contains a sample Maven Webapp project.)
...
Choose a number: 79:82
Choose version:
...
5: 1.0
Choose a number: 5:5
Define value for property 'groupId': :com.siark.igallery
Define value for property 'artifactId': :igallery
Define value for property 'version': 1.0-SNAPSHOT:
Define value for property 'package': com.siark.igallery:
Confirm properties configuration:
groupId: com.siark.igallery
artifactId: igallery
version: 1.0-SNAPSHOT
package: com.siark.igallery
Y:
3 Copy the contents of the pom.xml in the ~/Development/igallery directory to the empty pom.xml in the igallery Eclipse project.
4 In Eclipse, open the ‘Team Synchronising’ perspective from the ‘Window -> Open Perspective -> Other…’ dialog box.
3 Click the ‘Synchronize’ button to display the ‘Synchronize’ dialog. Select the ‘SVN’ option and press the ‘Next >’ button.
4 On the next ‘Synchronise’ dialog choose the ‘igallery’ project from the ‘Availible resources to Synchronize:’ section. Click the ‘Finish’ button. The igallery project should appear in the ‘Synchronise’ tab of this perspective.
5 The pom.xml file should be listed under the igallery project in the ‘Synchronize’ tab. Right click the pom.xml file and choose ‘Commit…’. In the dialog box that appears, enter a suitable comment to accompany the commit and press the ‘ok’ button.
6 To build the project using the m2eclipse Eclipse plugin, from the Java EE perspective right click the igallery project in the ‘Project Explorer’ and choose ‘Maven package’ from the ‘Run As’ menu item. This will generate a ‘target’ directory in the igallery directory containing amongst other things an igallery.war file. The ‘package’ Maven 2 lifecycle phase does everything except integration tests, installing the WAR file into the repository and deploying the WAR file to Tomcat.
September 15, 2010
Maven 2 and Nexus on OS X Snow Leopard
If you have the OS X Developer Tools (Xcode) installed (I have version 3.2.3), it comes with Maven 2. A quick ‘$ which mvn’ reveals mvn to be in /usr/bin. /usr/bin/mvn is a sym link to /usr/share/maven/bin/mvn and /usr/share/maven is actually a sym link to /usr/share/java/maven-2.2.0.
Download the Nexus WAR file (I downloaded nexus-webapp-1.7.2.war). Rename the WAR file nexus.war. I did consider creating a nexus user as Nexus writes information to a directory called sonatype-work, which by default is located in the home directory of the user running Tomcat, but I thought might be better located in a nexus user home directory. However, I decided just to relocate the sonatype-work directory to /Library/Tomcat/Home instead.
I deployed the nexus.war using the Tomcat Web Application Manager. To do this navigate to http://localhost:8080/manager, and half way down the page is the Deploy section with a WAR file to deploy subsection. This will deploy (and expand) the nexus.war file, but doesn’t run it. Once the WAR file is expanded, the location of the sonatype-work directory can be changed by editing the nexus-work property in the plexus.poperties file located in the WEB-INF directory of the expanded Nexus WAR.
Start Nexus by pressing the start button in the Nexus entry of the Applications section of the Tomcat Web Application Manager. If you can’t see the Applications section, press the List Applications button in the Manager section.