What is in my Cloud Environment?

I put together Java sample applications using Spring 3.1. Using Spring’s Environment abstractions, we can gather details about the underlying platform.

See the following sample pages

Environment Bean

package com.gordondickens.roobees.util;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment;

import javax.annotation.PostConstruct;
import java.util.*;

public class MyEnvironment {
  private static final Logger logger = LoggerFactory.getLogger(MyEnvironment.class);
  @Value("#{ systemProperties['user.language'] }")
  private String varOne;

  @Value("#{ systemProperties }")
  private Properties systemProperties;

  @Value("#{ systemEnvironment }")
  private Properties systemEnvironment;

  @Value("#{ environment }")
  private StandardEnvironment environment;

  @Override
  public String toString() {
    return "\n\n********************** MyEnvironment: ["
      + "\n\tsystemProperties=" + formatMe(systemProperties.toString())
      + ", \n\n\tsystemEnvironment=" + formatMe(systemEnvironment.toString())
      + ", \n\n\tenvironment=" + formatMe(environment.toString()) + "]";
  }

  private static String formatMe(final String in) {
    String out = in;
    out = in.replace("{", "{\n\t\t");
    out = out.replace(", ", "\n\t\t");
    return out;
  }

  @PostConstruct
  public void afterInstantiation() {
    logger.debug(this.toString());
  }

  public StandardEnvironment getEnvironment() {
    return environment;
  }

  public Properties getSystemEnvironment() {
    return systemEnvironment;
  }

  public Map<String,String> getSortedSystemEnvironment() {
    Properties p = systemEnvironment;
    Object[] keys = p.keySet().toArray();
    Arrays.sort(keys);
    Map<String, String> treeMap = new TreeMap<String, String>();
    treeMap.putAll((Map) p);
    return treeMap;
  }

  public Properties getSystemProperties() {
    return systemProperties;
  }

  public Map<String,String> getSortedSystemProperties() {
    Properties p = systemProperties;
    Object[] keys = p.keySet().toArray();
    Arrays.sort(keys);
    Map<String, String> treeMap = new TreeMap<String, String>();
    treeMap.putAll((Map) p);
    return treeMap;
  }

  public List<String> getServletConfigInitParams() {
    return getPropertyList("servletConfigInitParams");
  }

  public List<String> getServletContextInitParams() {
    return getPropertyList("servletContextInitParams");
  }

  public List<String> getJndiProperties() {
    return getPropertyList("jndiProperties");
  }

  private List<String> getPropertyList(String propSrcName) {
    if (environment.getPropertySources().contains(propSrcName)) {
      PropertySource ps = environment.getPropertySources().get(propSrcName);
      String results = ReflectionToStringBuilder.toString(ps, ToStringStyle.SHORT_PREFIX_STYLE);
      List<String> resultList = Arrays.asList(StringUtils.split(results, ','));
      Collections.sort(resultList);
      return resultList;
    } else
        return null;
  }
}

Wire in the Bean

If you want the environment information logged, then invoke the afterInstantiation method. It is marked as @PostConstruct, so it will automatically invoke if you use <context:annotation-config/> or <context:component-scan ... /> as long as component-scan includes the package, or package parents of the class.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans.xsd">

...

  <bean id="myEnvironment"
      class="com.gordondickens.roobees.util.MyEnvironment"
      init-method="afterInstantiation"/>

...

</beans>

Source Code

See my Roo CloudBees Demo Code – https://github.com/gordonad/gordonad-roo-1.2-cloudbees

My Cloud Presentations

Posted in Cloud, CloudBees, Heroku, Jelastic, Spring, Spring Roo | Tagged , , , , , , , | Leave a comment

Configuring Spring Roo for Java 7

When creating a Roo project with the “project” command, we have the option to specify the Java Version

$ roo
roo> project --topLevelPackage com.gordondickens.myproj --java 6 --projectName testapp

If we choose Java 7 with Roo 1.2.1, the code will not compile with AspectJ included.

Steps to change to Java 7:

  • Change the Java version to 1.7
  • Set the AspectJ version to 1.7.0.M1 or higher
  • Set the Maven AspectJ Plugin to 1.4 or higher
  • If using Hypersonic, change the version to 2.2.8 or higher
  • Change the Hibernate version to 4.1.2 or higher
  • (optional) Change the Hibernate Entity Manager to 4.1.2 or higher
<properties>
  <aspectj.version>1.7.0.M1</aspectj.version>
  <java.version>1.7</java.version>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <roo.version>1.2.1.RELEASE</roo.version>
  <slf4j.version>1.6.4</slf4j.version>
  <spring.version>3.1.1.RELEASE</spring.version>
</properties>
...
<dependency>
  <groupId>org.hsqldb</groupId>
  <artifactId>hsqldb</artifactId>
  <version>2.2.8</version>
</dependency>
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-core</artifactId>
  <version>4.1.2</version>
</dependency>
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-entitymanager</artifactId>
  <version>4.1.2</version>
  <exclusions>
    <exclusion>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
    </exclusion>
    <exclusion>
      <groupId>dom4j</groupId>
      <artifactId>dom4j</artifactId>
    </exclusion>
  </exclusions>
</dependency>
...
<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>aspectj-maven-plugin</artifactId>
  <version>1.4</version>
  <dependencies>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>${aspectj.version}</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjtools</artifactId>
      <version>${aspectj.version}</version>
    </dependency>
  </dependencies>
  <executions>
    <execution>
      <goals>
        <goal>compile</goal>
        <goal>test-compile</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
    <outxml>true</outxml>
    <aspectLibraries>
      <aspectLibrary>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
      </aspectLibrary>
    </aspectLibraries>
    <source>${java.version}</source>
    <target>${java.version}</target>
  </configuration>
</plugin>
...
Posted in AOP, AspectJ, Java, Java 7, JDK7, Maven, Roo, Spring, Spring AOP, Spring Data, Spring MVC | Tagged , , , , , , | Leave a comment

Quick Install Open Source Apps on Mac OSX

A quick way to install many of your Open Source applications & tools on the Mac OSX is with HomeBrew.

More and more, I am finding HomeBrew “recipes” for my commonly used applications, tools, etc. such as:

Applications

  • activemq
  • gradle
  • grails
  • groovy
  • rabbitmq
  • spring-roo

Tools

  • cmake
  • curl
  • git
  • gnupg
  • hub
  • libyaml
  • subversion
  • tree
  • wget

Languages

  • clojure
  • erlang
  • scala

Databases

  • mongodb
  • mysql
  • postgresql
  • redis

Installation

HomeBrew Installation Instructions.

Finding a Recipe (application)

$ brew search subversion

Installing a Recipe

$ brew install spring-roo

Updating a Recipe

$ brew upgrade spring-roo

Trouble?

$ brew doctor

More Brew Commands


Setting Up the Environment

Paths to the executables are setup, to configure the home directories many of the projects are configured using the “libexec” subdir.

export ACTIVEMQ_HOME=/usr/local/Cellar/activemq/5.5.1/libexec
export ACTIVEMQ_BASE=$ACTIVEMQ_HOME
export GRADLE_HOME=/usr/local/Cellar/gradle/1.0-milestone-8/libexec
export GRAILS_HOME=/usr/local/Cellar/grails/2.0.1/libexec
export GROOVY_HOME=/usr/local/Cellar/groovy/1.8.5/libexec
export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home
export M2_HOME=/usr/local/Cellar/maven/3.0.4/libexec
export M2_REPO=~/.m2
export MAVEN_HOME=$M2_HOME
export MYSQL_HOME=/usr/local/Cellar/mysql/5.5.19
export PGSQL_HOME=/usr/local/Cellar/postgresql/9.1.2
export RABBITMQ_HOME=/usr/local/Cellar/rabbitmq/2.7.1
export ROO_HOME=/usr/local/Cellar/spring-roo/1.2.1
export SVN_HOME=/usr/local/Cellar/subversion/1.7.3/libexec

#################################
# ###  HOMEBREW Essentials  ### #
#################################
export HOMEBREW_LIBRARY_PATH=$HOMEBREW_LIBRARY_PATH:$LD_LIBRARY_PATH
export CPLUS_INCLUDE_PATH=/usr/local/include:$CPLUS_INCLUDE_PATH
export PYTHONPATH=/usr/local/lib/python2.7/site-packages:/usr/local/lib/python:$PYTHONPATH
export LDFLAGS=-L/usr/local/Cellar/readline/6.2.2/lib
export CPPFLAGS=-I/usr/local/Cellar/readline/6.2.2/include
export TMPDIR=~/tmp

IntelliJ IDEA Users

Set the home variables (as above) in the ~/.MacOSX/environment.plist file. This file can be edited with Xcode or other plist editors.

Essential Recipes

$ brew install wget cmake libyaml --universal

Python Goodies

See the environment variables above, but first install the python pip package manager, mercurial & pyyaml.
$ sudo easy_install pip
$ sudo pip install mercurial pyyaml

The Path

Ensure the gcc and bin directories are in your path.
export PATH=/Developer/usr/llvm-gcc-4.2:/Developer/usr/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/X11/bin:.:$PATH


Survival Tips

Brew DOs

  • When updating use brew upgrade
  • Install XCode
  • Do NOT use macports
  • After installing each Recipe, check by running the app command with --version, i.e. roo --version

Brew DON’Ts

  • Do NOT use brew update – does not always work, use brew upgrade
  • Do NOT use sudo
  • Do NOT use macports

Want More?

Posted in HomeBrew, Installation | Tagged , , , , , , | Leave a comment

Installing and Configuring RabbitMQ

rabbitmq logo

RabbitMQ and AMQP (Advanced Message Queuing Protocol) are gaining momentum in the market. One of the main reasons for that momentum is because, in enterprise development, the client is not always Java specific. With RabbitMQ, we can configure a scalable, fault-tolerant, open-source messaging solution for polyglot clients, click here to see a list of client language support.

Follow the steps below to install and configure RabbitMQ v1.7.x on a MAC with OSX Lion. Click here for installation instructions for Windows and other platforms.


1. Installing RabbitMQ

Mac OSX Lion Installation

Install HomeBrew

From the terminal prompt:

$ brew install rabbitmq

We do NOT need to install Erlang, however, if desired use Brew as follows:

$ brew install erlang

HomeBrew RabbitMQ Directories

  • Logs: /usr/local/var/log/rabbitmq
  • Config: /usr/local/etc/rabbitmq
  • Mnesia Database: /usr/local/var/lib/rabbitmq/mnesia
  • Erlang cookie: <homedir>/.erlang.cookie

Mnesia is a NoSql database that stores RabbitMQ configuration data – Mnesia Reference Manual.


2. Configuring RabbitMQ Server

When RabbitMQ is installed, not all of the configuration files exist.

Do not be concerned if the install does not contain the files mentioned, simply create the text files and use the contents provided below as a base.

In the rabbitmq-env.conf file, any variables referenced can be set using an environment variable with the prefix RABBITMQ_, for example NODE_PORT=5672 can be set as an environment variable export RABBITMQ_NODE_PORT=5672

N.B. the system name in the examples is “Technophiliac”. In configuring your system, simply change all references from “Technophiliac” to your system name.

RabbitMQ Environment Configuration File

Create or edit /usr/local/etc/rabbitmq/rabbitmq-env.conf

# ##############################
# RABBITMQ SERVER CONFIGURATION
#
# All of the parameters below can also
#   be set as environment variables
#   using the prefix "RABBIT_"
#   i.e.  export RABBITMQ_NODE_PORT=5672
## ##############################

# ##########################
# Defaults to the empty string
#   meaning bind to all network interfaces
# Change to bind to one network interface only
# ##########################
# NODE_IP_ADDRESS=
# NODE_PORT=5672

# ##########################
# Unix, Linux: `env hostname`
# MacOSX: `env hostname -s`
# The name of the current machine
# ##########################
# HOSTNAME=

# ##########################
# The name of the current machine
# ##########################
# COMPUTERNAME=

# ##########################
# This base directory contains sub-directories for
#   server's db and log files
# Alternatively, set MNESIA_BASE and LOG_BASE individually
# ##########################
# BASE=

# ##########################
# Mac/Unix: rabbit@$HOSTNAME
# The node name should be unique per erlang-node-and-machine combination
# To run multiple nodes, see the clustering guide
# ##########################
# NODENAME=

# ##########################
# Mac: /usr/local/etc/rabbitmq/rabbitmq
# If the configuration file is present it is used by the server
# The .config extension is automatically appended
# This file is also used to auto-configure RabbitMQ clusters
# Example:
#   Config file location and new filename bunnies.config
#   CONFIG_FILE=/usr/local/etc/rabbitmq/bunnies
# ##########################
CONFIG_FILE=/usr/local/etc/rabbitmq/rabbitmq

# ##########################
# Mac: /usr/local/var/lib/rabbitmq/mnesia
# The Mnesia database files directory
#
# MNESIA_DIR will be assembled as MNESIA_BASE/NODENAME
# ##########################
# MNESIA_BASE=
# MNESIA_DIR=

# ##########################
# Mac: /usr/local/var/log/rabbitmq
# Log files generated by the server will be placed in this directory.
# ##########################
# LOG_BASE=/usr/local/var/log/rabbitmq

# ##########################
# The plugins directory
# ##########################
PLUGINS_DIR=/usr/local/Cellar/rabbitmq/2.7.1/lib/rabbitmq/erlang/lib/rabbitmq-2.7.1/plugins

# ##########################
# Mac: /usr/local/etc/rabbitmq/enabled_plugins
# This file declares explicitly enabled plugins
# ##########################
ENABLED_PLUGINS_FILE=/usr/local/etc/rabbitmq/enabled_plugins

RabbitMQ Server Configuration File

Create or edit the file /usr/local/etc/rabbitmq/rabbitmq.config

[{auth_backends,[rabbit_auth_backend_internal]},
 {auth_mechanisms,['PLAIN','AMQPLAIN']},
 {backing_queue_module,rabbit_variable_queue},
 {cluster_nodes,[]},
 {collect_statistics,fine},
 {collect_statistics_interval,5000},
 {default_permissions,[<<".*">>,<<".*">>,<<".*">>]},
 {default_user,<<"guest">>},
 {default_user_tags,[administrator]},
 {default_vhost,<<"/">>},
 {delegate_count,16},
 {error_logger,{file,"/usr/local/var/log/rabbitmq/rabbit@Technophiliac.log"}},
 {frame_max,131072},
 {hipe_compile,false},
 {included_applications,[]},
 {msg_store_file_size_limit,16777216},
 {msg_store_index_module,rabbit_msg_store_ets_index},
 {queue_index_max_journal_entries,262144},
 {sasl_error_logger,{file,"/usr/local/var/log/rabbitmq/rabbit@Technophiliac-sasl.log"}},
 {server_properties,[]},
 {ssl_listeners,[]},
 {ssl_options,[]},
 {tcp_listen_options,
   [binary,
     {packet,raw},
     {reuseaddr,true},
     {backlog,128},
     {nodelay,true},
     {exit_on_close,false}]},
 {tcp_listeners,[5672]},
 {trace_vhosts,[<<"/">>]},
 {vm_memory_high_watermark,0.4}]


3. Configuring RabbitMQ Console Plugins

RabbitMQ Console Plugins File

Create or edit the text file /usr/local/etc/rabbitmq/enabled_plugins

Include the following content (don’t forget the period at the end)

[rabbitmq_jsonrpc_channel,
 rabbitmq_jsonrpc_channel_examples,
 rabbitmq_management,
 rabbitmq_management_visualiser,
 rabbitmq_tracing].


4. Set Environment Variables

export RABBITMQ_HOME=/usr/local/Cellar/rabbitmq/2.7.1
export HOMEBREW_LIBRARY_PATH=$HOMEBREW_LIBRARY_PATH:$LD_LIBRARY_PATH
export CPLUS_INCLUDE_PATH=/usr/local/include:$CPLUS_INCLUDE_PATH
export PYTHONPATH=/usr/local/lib/python2.7/site-packages:/usr/local/lib/python:$PYTHONPATH
export LDFLAGS=-L/usr/local/Cellar/readline/6.2.2/lib
export CPPFLAGS=-I/usr/local/Cellar/readline/6.2.2/include


5. Starting RabbitMQ

$ sudo rabbitmq-server

We will see the following console output:

Activating RabbitMQ plugins ...
12 plugins activated:
* amqp_client-0.0.0
* mochiweb-1.3-rmq0.0.0-git
* rabbitmq_jsonrpc-0.0.0
* rabbitmq_jsonrpc_channel-0.0.0
* rabbitmq_jsonrpc_channel_examples-0.0.0
* rabbitmq_management-0.0.0
* rabbitmq_management_agent-0.0.0
* rabbitmq_management_visualiser-0.0.0
* rabbitmq_mochiweb-0.0.0
* rabbitmq_tracing-0.0.0
* rfc4627_jsonrpc-0.0.0-git
* webmachine-1.7.0-rmq0.0.0-hg

+---+   +---+
|   |   |   |
|   |   |   |
|   |   |   |
|   +---+   +-------+
|                   |
| RabbitMQ  +---+   |
|           |   |   |
|   v2.7.1  +---+   |
|                   |
+-------------------+
AMQP 0-9-1 / 0-9 / 0-8
Copyright (C) 2007-2011 VMware, Inc.
Licensed under the MPL.  See http://www.rabbitmq.com/

node           : rabbit@Technophiliac
app descriptor : /usr/local/Cellar/rabbitmq/2.7.1/lib/rabbitmq/erlang/lib/rabbitmq-2.7.1/ebin/rabbit.app
home dir       : /Users/gordondickens
config file(s) : /usr/local/etc/rabbitmq/rabbitmq.config
cookie hash    : VBuPLzEtAR8Sdq9eR1g36w==
log            : /usr/local/var/log/rabbitmq/rabbit@Technophiliac.log
sasl log       : /usr/local/var/log/rabbitmq/rabbit@Technophiliac-sasl.log
database dir   : /usr/local/var/lib/rabbitmq/mnesia/rabbit@Technophiliac
erlang version : 5.8.5

-- rabbit boot start
starting file handle cache server                                     ...done
starting worker pool                                                  ...done
starting database                                                     ...done
starting codec correctness check                                      ...done
-- external infrastructure ready
starting plugin registry                                              ...done
starting auth mechanism cr-demo                                       ...done
starting auth mechanism amqplain                                      ...done
starting auth mechanism plain                                         ...done
starting statistics event manager                                     ...done
starting logging server                                               ...done
starting exchange type direct                                         ...done
starting exchange type fanout                                         ...done
starting exchange type headers                                        ...done
starting exchange type topic                                          ...done
-- kernel ready
starting alarm handler                                                ...done
starting node monitor                                                 ...done
starting cluster delegate                                             ...done
starting guid generator                                               ...done
starting memory monitor                                               ...done
-- core initialized
starting empty DB check                                               ...done
starting management agent                                             ...done
starting exchange, queue and binding recovery                         ...done
starting mirror queue slave sup                                       ...done
starting adding mirrors to queues                                     ...done
-- message delivery logic ready
starting error log relay                                              ...done
starting networking                                                   ...done
starting direct_client                                                ...done
starting notify cluster nodes                                         ...done

broker running
** Found 0 name clashes in code paths


The Console

After RabbitMQ starts, go to the console http://localhost:55672/
NOTE: The default user id/password is guest/guest.


Summary

In this blog we saw the steps to install and configure RabbitMQ to run locally on Mac OSX Lion. In the next blog, I’ll introduce the concepts of AMQP exchanges, routes and queues, using Groovy Scripts to create and test them. We will also discover how to visualize those components and their relationships within the console.

Posted in AMQP, Erlang, HomeBrew, RabbitMQ | Tagged , , , | 1 Comment

Unit Testing Spring with Mockito & PowerMock

Unit Testing Spring with Mockito & PowerMock

I’ve updated my Spring Mockito Demo app that I demonstrate when teaching with a PowerMock of a final class with a static method.



Demo Features

  • Maven 3.0
  • Maven Enforcer plugin restricting use of commons-logging, log4j, slf4j > 1.5, maven version range & java 1.6
  • All Maven plugin and java dependency versions are current and managed in properties of pom.xml
  • Maven Versions plugin for evaluating current configuration for any version updates of dependencies
    • mvn versions:display-dependency-updates scans dependencies and reports dependencies with newer versions
    • mvn versions:display-plugin-updates scans plugins and reports plugins with newer versions
    • To get the version changes w/o the ones that haven’t changed : mvn versions:display-dependency-updates | grep " -> "
  • Logback configuration with SLF4J
  • Mockito tests of the controller layer (services are mocked)
  • PowerMock configuration testing a final class with static method
  • All tests are true Unit tests, no use of Spring Context in tests, including the context creates integration tests

Code Repository

https://github.com/gordonad/core-spring-demos/tree/master/demos/mockitodemo




Want to Learn More?

Learn more about Spring by attending a Spring Training class at Chariot, or contact us for onsite training.



Follow Chariot Education on Twitter

for Special Training offers

Posted in LogBack, Logging, Maven, Mocking, Mockito, PowerMock, SLF4J, Spring Framework, Spring MVC, Testing | Tagged , , , , , , , , | Leave a comment

Buzzing the Cloud with CloudBees and Roo

Looking to try out CloudBees for your Spring application?

Here is how you can get started quickly with CloudBees Run@Cloud platform.

05-Mar-12 – Updated for Spring Roo 1.2.1

  1. Get a CloudBees Account
  2. Configure a MySql instance on CloudBees
  3. Build a Spring Roo application
    see script below
  4. Create a cloudbees-web.xml file in WEB-INF
    same directory as web.xml
  5. Add Maven CloudBees Plugin
  6. Build and deploy with Maven
    mvn clean install bees:deploy


Roo 1.2.1 Script

Here is a simple item manager application script you can use/customize to create your application.

  • NOTE: Provide MySQL credentials in the “jpa setup” line.
# FOR SPRING ROO 1.2.1 - Spring Data JPA and Service Layer

development mode --enabled true

project --topLevelPackage com.gordondickens.roobees --java 6 --projectName roobees

jpa setup --provider HIBERNATE --database MYSQL --userName yourmysqluserid --databaseName yourmysqlinstancename --password yourmysqlpasswd

entity jpa --class ~.domain.Item --activeRecord false

field string --fieldName name --sizeMin 3 --sizeMax 30 --class ~.domain.Item
field string --fieldName description --sizeMax 255 --class ~.domain.Item

repository jpa --interface ~.repository.ItemRepository --entity ~.domain.Item

service --interface ~.service.ItemService --entity ~.domain.Item

web mvc setup
web mvc all --package ~.web

logging setup --level DEBUG


Roo 1.1.5 Script

Here is a simple item manager application script you can use/customize to create your application

# FOR SPRING ROO 1.1.5

development mode --enabled true

project --topLevelPackage com.gordondickens.roobees --java 6 --projectName roobees

persistence setup --provider HIBERNATE --database MYSQL --userName yourmysqluserid --databaseName yourmysqlinstancename --password yourmysqlpasswd

entity --class ~.domain.Item

field string --fieldName name --sizeMin 3 --sizeMax 30 --class ~.domain.Item
field string --fieldName description --sizeMax 255 --class ~.domain.Item

web mvc setup
web mvc all --package ~.web

logging setup --level DEBUG


cloudbees-web.xml

<?xml version="1.0"?>
<cloudbees-web-app xmlns="http://www.cloudbees.com/xml/webapp/1">
  <appid>roobees</appid>
  <context-param>
    <param-name>application.environment</param-name>
    <param-value>prod</param-value>
  </context-param>
</cloudbees-web-app>


Maven CloudBees Plugin

Add the CloudBees repository to the pluginRepositories section.

<pluginRepositories>
  ...
  <pluginRepository>
    <id>bees-plugins-snapshots</id>
    <url>http://repository-cloudbees.forge.cloudbees.com/public-snapshot/</url>
    <releases>
      <enabled>false</enabled>
    </releases>
    <snapshots>
      <enabled>true</enabled>
    </snapshots>
  </pluginRepository>
  ...
</pluginRepositories>

Add the CloudBees Maven plugin to the plugins section.

<plugins>
  ...
  <plugin>
    <groupId>com.cloudbees</groupId>
    <artifactId>bees-maven-plugin</artifactId>
    <version>1.0-SNAPSHOT</version>
    <configuration>
       <!-- your username/appname -->
      <appid>youruserid/roobees</appid>
      <!-- your api key -->
      <apikey>BEBEBE2CEBEBEFBE</apikey>
      <!-- your secret key -->
      <secret>GEE0GERE0E-JE0EQETEHEPET+33MEIEIEI0EEZEEIEE00+</secret>
      <message>Roo ItemManager on CloudBees by Gordon Dickens</message>
    </configuration>
  </plugin>
  ...
</plugins>


Database Properties File

Edit the /src/main/resources/META-INF/spring/database.properties file.
Set the database.url to jdbc:cloudbees://yourmysqlinstance.
Set the database.driverClassName to com.cloudbees.jdbc.Driver.

database.username=yourmysqluserid
database.password=yourmysqlpasswd

database.url=jdbc:cloudbees://yourmysqlinstancename
database.driverClassName=com.cloudbees.jdbc.Driver

Download the Demo App

The demo app is in Git https://github.com/gordonad/gordonad-roo-1.2-cloudbees for Spring Roo 1.2.



Get Your Copy -->
Get it NOW! -->
Spring Roo in Action Image <-- All the cool kids have one
<-- You gotta have it!




Want to Learn More?

Learn more about Spring by attending a Spring Training class at Chariot, or contact us for onsite training.



Follow Chariot Education on Twitter

for Special Training offers

Posted in Cloud, CloudBees, Roo, Spring, Spring Roo | Tagged , , , | 6 Comments

Rocket to the Cloud Fast with Roo

Want to build a Spring 3 application FAST and run it on the Cloud?

It is incredibly easy to do with Spring Roo and CloudFoundry!

This post on using Postgres on CloudFoundry helped me get started, however I tried using the 1.2.M1 with the CloudFoundry addon, but was unable to install it successfully in either 1.1.5.RELEASE or 1.2.0.M1.

Recently, Spring Roo moved to GitHub


Steps

  1. Get a Free CloudFoundry Account
  2. Clone the Spring Roo Git Repository
  3. Configure GPG/PGP setup
    see /spring-roo/readme.txt
  4. Build Spring Roo with Maven
    mvn -U clean install -Dgpg.passphrase=yourpassphrase
  5. Link the Roo startup script
    see /spring-roo/readme.txt


Creating a Project

  1. Make a directory for your SimpleItem project
    mkdir /SimpleItem
  2. Go to the directory
    cd /SimpleItem
  3. Create the script file simpleitem.roo in the /SimpleItem directory
    (see the contents below)
  4. Start roo-dev
  5. Type the command
    script --file simpleitem.roo
  6. Go To: http://mysimpleitem.cloudfoundry.com/


The simpleitem.roo script file

development mode --enabled true
project --topLevelPackage com.gordondickens.simpleitem --java 6 --projectName SimpleItem
jpa setup --provider HIBERNATE --database POSTGRES
entity --class ~.domain.Item --testAutomatically --activeRecord false
field string --fieldName name --sizeMin 3 --sizeMax 30 --class ~.domain.Item
field string --fieldName description --sizeMax 255 --class ~.domain.Item
field date --fieldName visitDate --type java.util.Date --notNull --past
repository jpa --interface ~.repository.ItemRepository --entity ~.domain.Item
service --interface ~.service.ItemService --entity ~.domain.Item
finder add --finderName findItemsByName --class ~.domain.Item
finder add --finderName findVisitsByDescriptionLike
web mvc setup
web mvc all --package ~.web
web mvc finder all
logging setup --level DEBUG
perform package
download accept terms of use
pgp automatic trust

# ###########
# NOTE: Provide your credentials here, or perform these steps at the Roo prompt
# ###########
cloud foundry login --email you@mycompany.com --password n00n3w1llgu3ss

# ###########
# NOTE: The war file is the "--projectName" specified above
# ###########
cloud foundry deploy --appName mysimpleitem --path /target/SimpleItem-0.1.0.BUILD-SNAPSHOT.war --memory 512
cloud foundry create service --serviceName mysimpleitem-postgres --serviceType postgresql
cloud foundry bind service --serviceName mysimpleitem-postgres --appName mysimpleitem
cloud foundry start app --appName mysimpleitem

# ###########
# Go to URL: http://mysimpleitem.cloudfoundry.com/



NOTE CloudFoundry is Public

Since CloudFoundry is public, you may run into an issue deploying the application with the name above. You should change the --projectName to something unique with your name in it such as yourname-simpleitem.

Gunnar Hillert’s Blog explains this well.



Adding CloudFoundry Plugin to Maven

Thanks to Gunnar Hillert’s post, we can add to our project’s Maven pom.xml file the CloudFoundry Plugin.

<plugins>
  ...
  <plugin>
    <groupId>org.cloudfoundry</groupId>
    <artifactId>cf-maven-plugin</artifactId>
    <version>1.0.0.M1</version>
    <configuration>
      <server>mycloudfoundry-instance</server>
      <target>http://api.cloudfoundry.com</target>
      <url>${project.name}.cloudfoundry.com</url>
      <memory>256</memory>
    </configuration>
  </plugin>
  ...
</plugins>



Add CloudFoundry Credentials

Add credentials to our userhome/.m2/settings.xml

<servers>
  ...
  <server>
    <id>mycloudfoundry-instance</id>
    <username>you@mycompany.com</username>
    <password>n00n3w1llgu3ss</password>
  </server>
  ...
</servers>

To push (deploy) the code to CloudFoundry type mvn cf:push
For more plugin details type mvn cf:help



Get Your Copy -->
Get it NOW! -->
Spring Roo in Action Image <-- All the cool kids have one
<-- You gotta have it!




Want to Learn More?

Learn more about Spring by attending a Spring Training class at Chariot, or contact us for onsite training.



Follow Chariot Education on Twitter

for Special Training offers

Posted in Cloud, CloudFoundry, Java, Roo, Spring, Spring Data, Spring Roo | Tagged , , , , , , , , | Leave a comment

SyntaxHighlighter Missing XRegExp.js

I just ran into an issue when I updated my javascript files for SyntaxHighlighter.

Looked at the error console and discovered that shCore.js could not find XRegExp.js.

This blog link was a great start.

Additional Details

  1. Syntax Highlighter Git Repo
  2. Get the XRegExp.js from the scripts directory: /SyntaxHighlighter/scripts/XRegExp.js
  3. In your page above the shCore.js add XRegExp.js

Page Header Example

<script src='js/jquery-1.6.3.min.js' type='text/javascript'></script>
<script type="text/javascript" src="js/syntaxhighlighter/XRegExp.js"></script>
<script type="text/javascript" src="js/syntaxhighlighter/shCore.js"></script>
<script type="text/javascript" src="js/syntaxhighlighter/shBrushPlain.js"></script>
<script type="text/javascript" src="js/syntaxhighlighter/shBrushJava.js"></script>
<script type="text/javascript" src="js/syntaxhighlighter/shBrushGroovy.js"></script>
<script type="text/javascript" src="js/syntaxhighlighter/shBrushXml.js"></script>
<script type="text/javascript" src="js/syntaxhighlighter/shBrushCss.js"></script>
<link href="css/syntaxhighlighter/shCore.css" rel="stylesheet" type="text/css">
<link href="css/syntaxhighlighter/shThemeDefault.css" rel="stylesheet" type="text/css">
Posted in JavaScript, jQuery, SyntaxHighlighter | Tagged , , , , , | Leave a comment

tcServer Logging with Logback & SLF4J

Logback and SLF4J provide better logging for java applications. To configure VMware vFabric tcServer to take advantage of the speed and flexibility of Logback use the following steps as a starting point.

Download the tcServer Developer Edition free: http://www.springsource.com/developer/tcserver
This comes with Spring Insight: http://www.springsource.org/insight an awesome tool for inspecting application performance, see those expensive sql queries, etc.



1. Add JMX options

File: <appname>/bin/setenv.sh

CATALINA_OPTS="-Dcom.sun.management.jmxremote"
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.ssl=false"
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.authenticate=false"



2. Enable JMX

File: <appname>/conf/server.xml

# In the <service> section:

<Connector port="8050"
  handler.list="mx"
  mx.enabled="true"
  mx.httpHost="localhost"
  mx.httpPort="8082"
  protocol="AJP/1.3" />



3. If using JNDI, add JNDI Configuration support for Logback

File: <appname>/bin/setenv.sh

JAVA_OPTS="$JAVA_OPTS -Dlogback.ContextSelector=JNDI"



4. Add Server Logging using Logback

File: <appname>/conf/server.xml

#In the <Hosts> Section:

<Valve className="ch.qos.logback.access.tomcat.LogbackValve" />



5. Create logback-access.xml file in <appname>/conf/ directory

<configuration>
  <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>combined</pattern>
    </encoder>
  </appender>

  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>myApp.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <fileNamePattern>myApp-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
      <timeBasedFileNamingAndTriggeringPolicy
            class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
        <maxFileSize>5MB</maxFileSize>
      </timeBasedFileNamingAndTriggeringPolicy>
    </rollingPolicy>
    <encoder>
      <pattern>combined</pattern>
    </encoder>
  </appender>

  <logger name="com.MYAPP.MYPKG" level="debug" />
  <logger name="org.springframework.web" level="debug" />
  <logger name="org.springframework.beans" level="debug" />
  <logger name="org.springframework.orm" level="debug" />
  <logger name="org.springframework.web" level="debug" />
  <logger name="net.sf.ehcache" level="error" />
  <logger name="org.hibernate.cache" level="error" />

  <root level="info">
    <appender-ref ref="FILE" />
    <appender-ref ref="STDOUT" />
  </root>
</configuration>



6. In the <tomcatdir>/lib directory, add the following jars

By including JCL-over-SLF4J, we handle Apache Commons Logging through SLF4J (JCL = Jakarta Commons Logging)
By including JUL-to-SLF4J, we handle Java Util Logging through SLF4J

  • jcl-over-slf4j-1.6.2.jar
  • jul-to-slf4j-1.6.2.jar
  • slf4j-api-1.6.2.jar
  • logback-access-0.9.30.jar
  • logback-classic-0.9.30.jar
  • logback-core-0.9.30.jar



7. Configure the application for Logging Separation

See: http://logback.qos.ch/manual/loggingSeparation.html

<env-entry>
  <description>JNDI logging context for this app</description>
  <env-entry-name>logback/context-name</env-entry-name>
  <env-entry-type>java.lang.String</env-entry-type>
  <env-entry-value>yourAppHere</env-entry-value>
</env-entry>

<env-entry>
  <description>URL for configuring logback context</description>
  <env-entry-name>logback/configuration-resource</env-entry-name>
  <env-entry-type>java.lang.String</env-entry-type>
  <env-entry-value>logback.xml</env-entry-value>
</env-entry>

<listener>
  <listener-class>ch.qos.logback.classic.selector.servlet.ContextDetachingSCL</listener-class>
</listener>

<filter>
  <filter-name>LoggerContextFilter</filter-name>
  <filter-class>ch.qos.logback.classic.selector.servlet.LoggerContextFilter</filter-class>
</filter>

<filter-mapping>
  <filter-name>LoggerContextFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>



8. Optional – To add a servlet to view the logback events

File: <application>/src/main/webapp/WEB-INF/web.xml
See: http://logback.qos.ch/manual/configuration.html
Status Messages will be available: http://yourWebapp/lbClassicStatus

<servlet>
  <servlet-name>ViewStatusMessages</servlet-name>
  <servlet-class>ch.qos.logback.classic.ViewStatusMessagesServlet</servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>ViewStatusMessages</servlet-name>
  <url-pattern>/lbClassicStatus</url-pattern>
</servlet-mapping>



Summary

Using tcServer with Insight provides us developers with a valuable resource for code inspection at runtime. Logback and SLF4J provides us with fast, flexible logging configuration and the logging separation for our application instances.




Want to Learn More?

Learn more about Spring by attending a Spring Training class at Chariot, or contact us for onsite training.



Follow Chariot Education on Twitter

for Special Training offers

Posted in Jakarta Commons Logging, Java, Java Util Logging, LogBack, Logging, SLF4J, Spring, Spring Insight, tcServer, Tomcat | Tagged , , , , , , | Leave a comment

Adding Queries to Spring Data-JPA

In my previous post, Simpler JPA with Spring Data-JPA I showed how to configure a repository interface which Spring Data will implement for us. Let me show how easy it is to add queries.



Modify the Repository Interface

Simply define the method interface and use the @Query annotation to define the OQL.

package com.gordondickens.myapp.repository;

import org.springframework.data.repository.CrudRepository;
import com.gordondickens.myapp.entity.Product;

public interface ProductRepository
   extends CrudRepository<Product, Long> {

	@Query("FROM Product")
	List<Product> findAllProducts();
}

Modifying Queries

  • Parameters can be marked by position with ?1, ?2, etc.
  • Parameters can be marked by name with :paramName and annotation @Param("paramName")
  • Modifying method signature can only return void, Integer or int
  • Updating queries MUST be transactional, mark with @Transactional
  • Spring Data will drop all non-flushed changes pending in the EntityManager, change with @Modifying(clearAutomatically=false)
package com.gordondickens.myapp.repository;

import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;

@Transactional(readOnly=true)
public interface ProductRepository
   extends CrudRepository<Product, Long> {

   @Query("FROM Product")
   List<Product> findAllProducts();

   // Example with positional params
   @Modifying
   @Transactional(readOnly=false)
   @Query("update Product p set p.description = ?2 where p.productId = ?1")
   Integer setNewDescriptionForProduct(String productId, String description);

   // Example with named params
   @Modifying
   @Query("update Product p set p.description = :description where p.productId = :productId")
   Integer setNewDescriptionForProduct(@Param("productId") String productId,
      @Param("description") String description);
}



Automatic Query Generation

The <jpa:repositories/> has an option query-lookup-strategy which defaults to “create-if-not-found” which will generate queries for us.

The default is “create-if-not-found“. Other options are “create” or “use-declared-query“.

   <jpa:repositories base-package="com.gordondickens.myapp.repository"
		query-lookup-strategy="create-if-not-found"/>

To create a find method that effectively does @Query("FROM Product p where p.productId = :productId")

public interface ProductRepository extends CrudRepository<Product, Long> {
   ...

   @Query
   Product findByProductId(String productId);

   ...



Summary

We see how simple interface additions provide custom methods based on query language. We can query either by positional or named parameters.




Want to Learn More?

Learn more about Spring by attending a Spring Training class at Chariot, or contact us for onsite training.



Follow Chariot Education on Twitter

for Special Training offers

Posted in Spring | 10 Comments