Sawing through the Java Loggers

Sawing through the Java Loggers

It's Log!

I know what your thinking, “It’s just logging!”. This small, yet common part of our applications, provides developers, QA and troubleshooters with information to help in determining code execution sequences, inspecting data values and trouble spots within our applications. The reality is that without robust logging implementations we would lose a significant troubleshooting tool.

Java Logging Choices

  1. System.out/System.err
  2. java.util.logging (JUL)
  3. Apache commons jogging (aka Jakarta Commons Logging – JCL)
  4. Log4j
  5. SLF4j
  6. Logback


System.out & System.err

In the early days (hopefully not now) we used to use the old System.out.println() method of logging. We would quickly discover using them is NOT good.

Reasons to avoid System methods

  • We can not disable in production, affecting performance and potentially compromising data security. Oh we do have System.err.println() but still not good enough
  • We can not configure how much or little information is reported (logging levels)
  • In a clustered environment, we can not configure a central location for information
  • System.out performs poorly… see Logging vs System.out Performance
  • Metadata is unavailable and must be coded for each System.out, which is inevitably not going to be done or very inconsistent at the least

*** DO NOT USE System.out or System.err anywhere, ever! ***


java.util.logging (JUL)

Java provides a logging option which is a step forward in logging. However, it is not widely used as it came late to the party. Not many open source frameworks use JUL. Typically you will find this in com.sun or com.oracle projects such as Jersey.


Log4j

Log4j is an Apache project that has been around for some time and is widely used by open source projects. Log4j provides a flexible logging framework but is a bit dated at this point.


SLF4j – Logging API

We have many options for logging, and with our open source projects we typically include projects that might implement JCL and JUL.

SLF4j (Simple Logging Facade for Java) provides a common logging interface for our projects. Most respectable open source projects now use SLF4j for the configurability and flexibility to change logging implementation. Think of SLF4j as the common interface (API) for our logging implementation choice.

All of our logging code should use the same SLF4j API. For example:

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
…

public class MyClass {
  private static final Logger logger = LoggerFactory.getLogger(MyClass.class);
…
 
  public void someMethod() {
    logger.debug("something is happening");
  }

}

Basic SLF4j Maven Dependencies

<properties>
  <slf4j.version>1.7.5</slf4j.version>
  <logback.version>1.0.11</logback.version>
</properties>

<dependencies>
  <!-- SLF4J - logging api -->
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>${slf4j.version}</version>
  </dependency>

  <!-- Logback - logging impl -->
  <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>${logback.version}</version>
  </dependency>
</dependencies>

Advanced SLF4j Maven Dependencies

<properties>
  <slf4j.version>1.7.5</slf4j.version>
  <logback.version>1.0.11</logback.version>
</properties>

<dependencies>
  <!-- SLF4J - logging api -->
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>${slf4j.version}</version>
  </dependency>
  <!--  Interceptor for Commons-logging -->
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jcl-over-slf4j</artifactId>
    <version>${slf4j.version}</version>
  </dependency>
  <!--  Interceptor for java.util.logging -->
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jul-to-slf4j</artifactId>
    <version>${slf4j.version}</version>
  </dependency>

  <!-- Logback - logging impl -->
  <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>${logback.version}</version>
  </dependency>
  <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>${logback.version}</version>
  </dependency>
</dependencies>

SLF4j Advantages

  • One logging strategy for all
  • String placeholders
    • logger.debug(“The value of {} is {}”, myVar, myValue);
  • Intercepts commons-logging
    • Include jcl-over-slf4j dependency
    • Should exclude commons-logging dependencies from project
  • Can intercept java.util.logging
  • Can intercept System.out & System.err


Logback – Smarter Logging

Logback is a project from the creator of Log4j and SLF4j, Ceki Gülcü (pronounced Jacky Guldju).

The first article to read is: Logback: Reasons to Switch

Simple logback.xml File

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true" scan="true" scanPeriod="30 seconds">

  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%-5level %logger{0} - %msg%n</pattern>
    </encoder>
  </appender>

  <logger name="com.gordondickens.demo" level="debug" />
  <logger name="org.springframework.beans" level="trace" />

  <root level="warn">
    <appender-ref ref="console" />
  </root>
</configuration>

File Appenders

In addition to the console appender, there are File and RollingFile. The Rolling file appender allows time-based and size-based options, with the ability to specify how many files to keep and optional compression (zip).
See: Logback Appenders

Speaks Native SLF4j

We saw above that simply replacing Log4j with Logback, we now have logging through SLF4j. Actually, its one dependency less, as we no longer would include the slf4j-log4j12 dependency.

RESTful & Web Access Logging

We can use logback-access to provide server access logging. This can prove to be very helpful when troubleshooting RESTful web services as well as for web applications. In our application’s src/main/resources directory create the file logback-access.xml.

logback-access.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />

  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${user.dir}/logs/app-access.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <fileNamePattern>${user.dir}/logs/app-access.%d{yyyy-MM-dd}.log.zip</fileNamePattern>
    </rollingPolicy>
    <encoder>
      <pattern>combined</pattern>
    </encoder>
  </appender>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%n%n%fullRequest%n%n%fullResponse%n%n</pattern>
    </encoder>
  </appender>

  <appender-ref ref="FILE" />
  <appender-ref ref="STDOUT" />
</configuration>

web.xml

The “TeeFilter” handles the access logging. See http://logback.qos.ch/access.html
The optional “ViewStatusMessagesServlet” allows us to browse the log back configuration via the url /logbackstatus. See http://logback.qos.ch/manual/configuration.html

<filter>
  <filter-name>TeeFilter</filter-name>
  <filter-class>ch.qos.logback.access.servlet.TeeFilter</filter-class>
</filter>

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

<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>/logbackStatus</url-pattern>
</servlet-mapping>

Test Specific Configuration

In our project’s src/main/resources we define a logback.xml file.
In our project’s src/test/resources we define a logback-test.xml file.

Conditional Configuration

Logback uses Janino allowing the ability to perform conditional configuration.

Janino Maven Dependency

<dependency>
  <groupId>org.codehaus.janino</groupId>
  <artifactId>janino</artifactId>
  <version>2.6.1</version>
</dependency>

Conditional Operations

  • boolean isDefined(String prop);
  • boolean isNull(String prop);
  • String p(String prop);
  • String property(String prop);


See: PropertyWrapperForScripts JavaDoc

<if condition='isDefined("catalina.home")'>
  <then>
    <property name="log.dir" value="${catalina.home}"/>
  </then>
  <else>
    <property name="log.dir" value="${user.dir}/logs"/>
  </else>
</if>

The cool thing is that we can use Spring 3 environment profiles spring.profiles.active. In the example below, the method property() or p() returns a String, so we can use String functions such as contains().

<if condition='property("spring.profiles.active").contains("dev")'>
  <then>
    <property name="log.dir" value="${catalina.home}"/>
  </then>
  <else>
    <property name="log.dir" value="${user.dir}/logs"/>
  </else>
</if>

Note: For testing, with Maven via the Jetty or Tomcat plugins, ${user.dir} resolves to the project home.

Modular Configuration

We can configure multiple configuration files, effectively segmenting our configuration. We could use a more detailed logging configuration for testing and a more conservative logging for production.

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true" scan="true" scanPeriod="5 seconds">
  <property resource="logconfig/logback.properties"/>

  <include resource="logconfig/headerconfig.xml"/>

  <if condition='property("spring.profiles.active").contains("dev")'>
    <then>
      <include resource="logconfig/springbeans.xml"/>
      <include resource="logconfig/hibernatefile.xml"/>
    </then>
    <else>
      <include resource="logconfig/productionfile.xml"/>
    </else>
  </if>

  <include resource="logconfig/consolelog.xml"/>

  <root level="warn">
    <appender-ref ref="console"/>
  </root>
</configuration>

hibernatefile.xml

Included files use are wrapped with the include tag.

<?xml version="1.0" encoding="UTF-8"?>
<included>
  <appender name="hibernatefile"
    class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${log.dir}/${hibernate.logfile}.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
      <fileNamePattern>${log.dir}/${hibernate.logfile}.%i.log.zip</fileNamePattern>
      <minIndex>1</minIndex>
      <maxIndex>6</maxIndex>
    </rollingPolicy>
    <triggeringPolicy
      class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
      <maxFileSize>50MB</maxFileSize>
    </triggeringPolicy>
    <encoder>
      <pattern>%date %level - %msg%n</pattern>
    </encoder>
  </appender>

  <logger name="org.springframework.orm" level="debug">
    <appender-ref ref="hibernatefile" />
  </logger>
  <logger name="org.springframework.jdbc" level="debug">
    <appender-ref ref="hibernatefile" />
  </logger>
  <logger name="org.springframework.transaction" level="debug">
    <appender-ref ref="hibernatefile" />
  </logger>
  <logger name="org.hibernate.ejb" level="debug">
    <appender-ref ref="hibernatefile" />
  </logger>
  <logger name="org.hibernate.sql" level="debug">
    <appender-ref ref="hibernatefile" />
  </logger>
  <logger name="org.hibernate.tool.hbm2ddl" level="debug">
    <appender-ref ref="hibernatefile" />
  </logger>
</included>


Summary

  • Do NOT use System.out or System.err
  • Use SLF4j parameter placeholder {} instead of string concatenation, this eliminates the need for isDebugEnabled() around our debug logging
  • Always define the Logger as private static final
  • Using SLF4j and Logback provides flexible, smart logging. We have tools that provide rich logging options for enterprise application development
    • Logback speaks natively to SLF4j
    • Java and Groovy configuration
    • Conditional Logging
    • Modular configuration
    • Access logging
    • Message filtering
    • Compression of rolled log files
    • Sifting Appenders by runtime attributes


Further Reading


Sources

Posted in Jakarta Commons Logging, Java Util Logging, LogBack, Logging, SLF4J | Tagged , , , , , | 4 Comments

Database Configuration with Spring 3.2 Environment Profiles

Database Configuration with Spring 3.2 Environment Profiles

This is a followup to my previous blog Spring 3.1 Environment Profiles

Let’s demonstrate how to configure an application to use different databases based on configuration. The code below is using Spring JavaConfig, in lieu of XML config.

Source Code: Spring Data Demos with Profile Example


Profiles

Spring 3.2 has improved the environment-aware profiles feature. Our applications can activate beans, at runtime, defined in specific profiles. For example to test different databases, we can use profiles such as Oracle, MySQL, HSQL, etc.

Let’s see how to configure a Spring application for multiple database vendor support to aid developers in testing with an in memory database (offline) before connecting to the enterprise database.

Common JPA Configuration

Since all of the classes will use JPA and Hibernate in these examples, there is clearly common configuration for all database vendors.

Common beans are typically DataSource, TransactionManager, EntityManager and EntityManagerFactory.

We’ll create configuration classes for the different database types in the package com.gordondickens.orm.config

├── db
│   ├── JpaCommonConfig.java
│   ├── JpaDerbyClientConfig.java
│   ├── JpaDerbyEmbeddedConfig.java
│   ├── JpaH2EmbeddedConfig.java
│   ├── JpaHsqlEmbeddedConfig.java
│   ├── JpaMySqlEmbeddedConfig.java
│   ├── JpaOracleConfig.java
│   ├── JpaOracleJndiConfig.java
│   └── JpaPostgresqlConfig.java
└── support
    ├── DatabaseConfigProfile.java
    └── Hbm2ddlType.java


JpaCommonConfig

  • @Configuration – defines this class as a Spring Configuration class
  • @PropertySource – loads in external properties into the Environment
  • @Bean – defines a Spring bean, where the bean name is defined by the method name and the type is defined by the return type
  • @Value – uses SpEL (Spring Expression Language) to extract property values from the autowired Environment, note the pound sign “#” indicates a bean reference
  • getDatabaseDialect() – is required to be implemented in concrete classes
  • getJpaProperties() – is expected to be implemented in concrete classes
  • The getters will provide values from the environment, via the concrete Jpa config classes
package com.gordondickens.orm.config.db;

import org.hibernate.dialect.Dialect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import javax.persistence.EntityManager;
import javax.sql.DataSource;
import java.util.Properties;

/**
 * Common Settings for JPA
 */
@Configuration
@PropertySource("classpath:/META-INF/spring/app-config.properties")
public abstract class JpaCommonConfig {
  public static final String UNDEFINED = "**UNDEFINED**";
  public static final String CONNECTION_CHAR_SET = "hibernate.connection.charSet";
  public static final String VALIDATOR_APPLY_TO_DDL = "hibernate.validator.apply_to_ddl";
  public static final String VALIDATOR_AUTOREGISTER_LISTENERS = "hibernate.validator.autoregister_listeners";

  @Autowired
  Environment environment;

  @Value("#{ environment['entity.package'] }")
  private String entityPackage = "com.gordondickens.orm.hibernate.domain";

  @Bean
  public abstract DataSource dataSource();

  @Bean
  public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setGenerateDdl(true);
    vendorAdapter.setDatabasePlatform(getDatabaseDialect().getName());
    vendorAdapter.setShowSql(true);

    LocalContainerEntityManagerFactoryBean factory =
        new LocalContainerEntityManagerFactoryBean();
    factory.setJpaVendorAdapter(vendorAdapter);
    factory.setPackagesToScan(entityPackage);
    factory.setDataSource(dataSource());
    if (getJpaProperties() != null) {
      factory.setJpaProperties(getJpaProperties());
    }
    return factory;
  }

  @Bean
  public EntityManager entityManger() {
    return entityManagerFactory().getObject().createEntityManager();
  }

  @Bean
  public PlatformTransactionManager transactionManager() {
    JpaTransactionManager txManager = new JpaTransactionManager();
    txManager.setEntityManagerFactory(entityManagerFactory().getObject());
    return txManager;
  }

  protected abstract Class<? extends Dialect> getDatabaseDialect();

  protected Properties getJpaProperties() {
    return null;
  }

  public String getDatabaseName() {
    return environment.getProperty("database.name", UNDEFINED);
  }

  public String getHost() {
    return environment.getProperty("database.host", UNDEFINED);
  }

  public String getPort() {
    return environment.getProperty("database.port", UNDEFINED);
  }

  public String getUrl() {
    return environment.getProperty("database.url", UNDEFINED);
  }

  public String getUser() {
    return environment.getProperty("database.username", UNDEFINED);
  }

  public String getPassword() {
    return environment.getProperty("database.password", UNDEFINED);
  }

  public String getDriverClassName() {
    return environment.getProperty("database.driverClassName", UNDEFINED);
  }

  public String getDialect() {
    return environment.getProperty("database.dialect", UNDEFINED);
  }

  public String getDatabaseVendor() {
    return environment.getProperty("database.vendor", UNDEFINED);
  }

  public String getHbm2ddl() {
    return environment.getProperty("database.hbm2ddl.auto", "none");
  }

  public String getHibernateCharSet() {
    return environment.getProperty("database.hibernateCharSet", "UTF-8");
  }

  public String getDatabaseValidationQuery() {
    return environment.getProperty("database.validation.query", UNDEFINED);
  }
}

Concrete Database Configuration Classes

Inherit from the JpaCommonConfig class to provide vendor specific configuration.

package com.gordondickens.orm.config.db;

import com.gordondickens.orm.config.support.DatabaseConfigProfile;
import com.gordondickens.orm.config.support.Hbm2ddlType;
import org.apache.commons.dbcp.BasicDataSource;
import org.hibernate.cfg.ImprovedNamingStrategy;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.HSQLDialect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.datasource.init.DatabasePopulator;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Properties;
import static java.lang.Boolean.TRUE;
import static org.hibernate.cfg.Environment.*;
import static org.hibernate.ejb.AvailableSettings.NAMING_STRATEGY;

/**
 * HSQL Embedded
 */
@Configuration
@Profile(DatabaseConfigProfile.HSQL_EMBEDDED)
@PropertySource("classpath:/META-INF/spring/hsql.properties")
public class JpaHsqlEmbeddedConfig extends JpaCommonConfig {

  @Override
  @Bean(destroyMethod = "close")
  public DataSource dataSource() {
    BasicDataSource dataSource = new BasicDataSource();
    dataSource.setDriverClassName(getDriverClassName());
    dataSource.setUrl(getUrl());
    dataSource.setUsername(getUser());
    dataSource.setPassword(getPassword());
    dataSource.setValidationQuery(getDatabaseValidationQuery());
    dataSource.setTestOnBorrow(true);
    dataSource.setTestOnReturn(true);
    dataSource.setTestWhileIdle(true);
    dataSource.setTimeBetweenEvictionRunsMillis(1800000);
    dataSource.setNumTestsPerEvictionRun(3);
    dataSource.setMinEvictableIdleTimeMillis(1800000);
    return dataSource;
  }

  @Override
  protected Properties getJpaProperties() {
    Properties properties = new Properties();
    properties.setProperty(HBM2DDL_AUTO, Hbm2ddlType.CREATE_DROP.toValue());
    properties.setProperty(GENERATE_STATISTICS, TRUE.toString());
    properties.setProperty(SHOW_SQL, TRUE.toString());
    properties.setProperty(FORMAT_SQL, TRUE.toString());
    properties.setProperty(USE_SQL_COMMENTS, TRUE.toString());
    properties.setProperty(CONNECTION_CHAR_SET, getHibernateCharSet());
    properties.setProperty(NAMING_STRATEGY, ImprovedNamingStrategy.class.getName());
    return properties;
  }

  @Override
  protected Class<? extends Dialect> getDatabaseDialect() {
    return HSQLDialect.class;
  }

  @Bean
  public DatabasePopulator databasePopulator(DataSource dataSource) {
    ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
    populator.setContinueOnError(true);
    populator.setIgnoreFailedDrops(true);
    // populator.addScript(new ClassPathResource("/sql/mydata-dml.sql"));
    try {
      populator.populate(dataSource.getConnection());
    } catch (SQLException ignored) {}
    return populator;
  }
}

Testing

JavaConfig allows us to configure Spring with or without XML configuration. If we want to test beans that are defined in a Configuration class we configure our test with the loader and classes arguments of the @ContextConfiguration annotation.


Test Context Configuration


Create a configuration class, bootstrapping the test context for the beans to be tested.

  • @ComponentScan – scans for annotated beans and entities. Note that @ComponentScan will ignore auto-discovery of other @Configuration classes
  • @EnableJpaRepositories – configures Spring-Data-JPA repository interfaces annotated with @Repository
  • @EnableTransactionManagement – proxies the @Transactional annotated classes
package com.gordondickens.orm.hibernate.config;

import com.gordondickens.orm.hibernate.domain.Employee;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.*;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * Test Configuration
 */
@Configuration
@ComponentScan(basePackages = "com.gordondickens.orm.hibernate",
    excludeFilters = {@ComponentScan.Filter(Configuration.class)})
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.gordondickens.orm.hibernate.repository")
public class TestConfig {

  @Bean
  @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
  public Employee employee() {
    return new Employee();
  }
}


JUnit Test

  • @ActiveProfiles – sets the valid profiles for the test execution similar to using the environment variable spring.profiles.active
  • @ContextConfiguration – sets up the test context. Here we load in the test bootstrap class and the vendor specific JPA configuration classes
package com.gordondickens.orm.hibernate.domain;

import com.gordondickens.orm.config.db.JpaHsqlEmbeddedConfig;
import com.gordondickens.orm.config.support.DatabaseConfigProfile;
import com.gordondickens.orm.hibernate.config.TestConfig;
import com.gordondickens.orm.hibernate.service.EmployeeService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;

import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.samePropertyValuesAs;
import static org.junit.Assert.assertThat;

@ActiveProfiles(DatabaseConfigProfile.HSQL_EMBEDDED)

@Transactional
@ContextConfiguration(classes = {JpaHsqlEmbeddedConfig.class, TestConfig.class})
@RunWith(SpringJUnit4ClassRunner.class)
public class EmployeeHsqlIntegrationTest {

  @Autowired
  EmployeeService employeeService;

  @Test
  public void testMarkerMethod() {
    Employee employee = new Employee();
    employee.setFirstName("Cletus");
    employee.setLastName("Fetus");

    employeeService.saveEmployee(employee);
    assertThat("Employee MUST exist", employee, notNullValue());
    assertThat("Employee MUST have PK", employee.getId(), notNullValue());

    Employee employee1 = employeeService.findEmployee(employee.getId());
    assertThat("Employee Must be Found by ID", employee1.getId(),
        samePropertyValuesAs(employee.getId()));
  }
}

Summary

Using the Profile feature, we can configure a database so run locally on an embedded database, such as Derby, HSQL, or H2. Using profiles gives developers the ability to validate entity and ORM configuration before connecting to the enterprise database, such as Oracle.

The example could be tuned to Component Scan configuration classes, eliminating the explicit include of the vendor specific JPA config class.

Sources

Spring Data Demos with Profile Example

Posted in Annotations, Java, JUnit, Spring, Spring Data, Testing | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , | 2 Comments

Enterprise Spring Best Practices – Part 4 – Annotation Config

Enterprise Spring Best Practices Series

In part 4, Spring Annotation Configuration.

In this edition of Enterprise Spring Best Practices, let’s look at annotations. Several of the annotations became available in Spring 2.5. Spring 3.0 added convenient annotation discovery mechanisms which we’ll see here.

Annotations are available for Dependency Injection, Bean discovery and instantiation, post processing (required fields, initialization method, etc).

Annotations may or may NOT be discovered in java interfaces, refer to the documentation or JavaDoc for details on whether the annotation discovery mechanism will traverse upward in the class hierarchy.


Sections




Annotation Style Decision



Annotations help simplify configuration. All annotations in Java 5 and above, require some discovery mechanism.

Within Spring, we have 3 strategies for bean discovery and dependency injection

  1. XML based discovery
  2. JavaConfig
  3. Hybrid Configuration

Hybrid configuration is simply mixing standard XML <bean/> declarations with annotation methods discussed below. In the next blog, I will discuss JavaConfig, so for now lets focus on XML based discovery of Annotations.



Annotation Discovery from XML



All annotations REQUIRE a discovery directive. We MUST know which XML directives discover particular annotations, or the beans will not be processed.
For Spring annotation discovery detail, see Annotation Reference for Spring Projects

Option 1 – Register individual bean post processors

There are several individual Bean Post Processors that can be registered to discover specific annotation categories

  • RequiredAnnotationBeanPostProcessor – (@Required)
  • CommonAnnotationBeanPostProcessor – (@PostConstruct, @PreDestroy, @Resource, etc.)
  • AutowiredAnnotationBeanPostProcessor – (@Autowired, @Value, @Inject, etc.)
  • PersistenceAnnotationBeanPostProcessor – (@PersistenceUnit, @PersistenceContext, etc.)

Option 2 – Use the annotation-config directive

Automatically registers the Bean Post Processors above.

  <context:annotation-config/>

Option 3 – Use the component-scan directive

Automatically registers the Bean Post Processors above AND scans for component annotations @Component, @Repository, @Service, @Controller, and more…

  <context:context:component-scan 
      base-package="com.gordondickens.enterprisespring"/>



Application Component Scanning



Exclude configuration elements that are not part of the underlying application. Controllers are part of the application that deals with the user interface but are not pertinent to Web Services.
Within applicationContext-bootstrap.xml

<context:component-scan 
  base-package="com.gordondickens.enterprisespring">
    
  <context:exclude-filter
    expression="org.springframework.stereotype.Controller"
    type="annotation"/>
</context:component-scan>



MVC Component Scanning



Exclude components are not part of the entire application. If our application serves UI clients and web service clients, only the base components should be discovered in the main application configuration. We will discuss MVC configuration in a future blog.

Within applicationContext-webmvc.xml

<context:component-scan 
  base-package="com.gordondickens.enterprisespring"
  use-default-filters="false"/>

    <context:include-filter 
      expression="org.springframework.stereotype.Controller" 
      type="annotation"/>
</context:component-scan>



Component Scanning Best Practices



When Spring creates the application context, it aggregates all of the configuration into a single context, no matter how many configuration files or annotations are used.

  • Component scanning should ONLY be configured in the bootstrap config file, not in every XML config file
  • Do NOT also include the <context:annotation-config/> directive, it is automatically included by component scan
  • Do NOT start scanning from “com” and/or “org”, as this will scan ALL sub packages in all of the project and jars for candidates!
  • Be as specific as possible with the packages
  • Do NOT cross application boundaries with component-scan
    • Create an applicationContext-services.xml for scanning services
    • Create an applicationContext-persistence.xml for persistence and entity beans
    • Create an applicationContext-webmvc.xml for persistence and entity beans
    • Create an applicationContext-webservice.xml for web service beans
    • Import these references into the applicationContext-bootstrap.xml to these elements

Why separate the discovery files into layer specific configuration?

  • Unit testing is easier as discovery of beans is more specific
  • Allows the project to be separated into multiple Jar/Wars
  • Lowers risk of widely scoped discovery issues, overscanning and beans being replaced by multiple scanners

For Spring annotation discovery detail, see Annotation Reference for Spring Projects



Further Reading




Social Me



Twitter – twitter.com/gdickens
LinkedIn – linkedin.com/in/gordondickens
GitHub: github.com/gordonad
gordon@gordondickens.com


Posted in Spring | Tagged , , , , , | Leave a comment

Maven 3 Code Analysis and Reporting

If you have read any of my other blogs, you will know that I am a fan (and defender) of Maven 3. One of the biggest changes in Maven 3 was the reporting capabilities with the Maven Site Plugin.

I will show example configuration for the Site 3.1 plugin using Markdown syntax for the page content and the Markdown project at Daring Fireball.

Most of us have multi projects to build. When I was setting up the Site configuration, I had to keep this in consideration. I ran into issues with aggregating reports, and AspectJ classes with Cobertura for code test coverage.

Old Config (a.k.a. things to forget)

The OLD Maven reporting section.

<reporting/>

New Config

The Maven Site 3.x plugin is a “container” for reporting plugins.

Here is a table of some of the more common open source plugins.

Report Description
Javadoc Generates JavaDoc
Java XRef Cross reference report of project source code
Tag List Reports on Tags such as @todo and //TODO
Project Info A plethora of miscellaneous report: info, ci, dependencies, scm, plugins, etc.
Check Style Checks Code Style for Developers
Surefire Reports Test Results
PMD Source Code Analyzer
FindBugs Reports on common code mistakes and pitfalls
Sonar Analysis and metrics on code over time
Cobertura Reports Test Coverage
Versions Reports on application and plugin versions, and any updates available

Configuration

...
<properties>
  <maven.checkstyle.plugin>2.7</maven.checkstyle.plugin>
  <maven.cobertura.plugin>2.5.1</maven.cobertura.plugin>
  <maven.doxia.module.markdown.version>1.3</maven.doxia.module.markdown.version>
  <maven.javadoc.plugin>2.9</maven.javadoc.plugin>
  <maven.jxr.plugin>2.3</maven.jxr.plugin>
  <maven.pmd.plugin>2.7.1</maven.pmd.plugin>
  <maven.project.info.reports.plugin>2.6</maven.project.info.reports.plugin>
  <maven.site.plugin>3.2</maven.site.plugin>
  <maven.sonar.plugin>3.3.1</maven.sonar.plugin>
  <maven.surefire.plugin>2.12.4</maven.surefire.plugin>
  <maven.taglist.plugin>2.4</maven.taglist.plugin>
  <maven.versions.plugin>1.3.1</maven.versions.plugin>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
...
<build>
  <plugins>
    <plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-site-plugin</artifactId>
	<version>${maven.site.plugin}</version>
	<executions>
	    <!-- used for multiproject builds -->
		<execution>
			<id>attach-descriptor</id>
			<goals>
				<goal>attach-descriptor</goal>
			</goals>
		</execution>
	</executions>
	<configuration>
		<reportPlugins>
        <!-- Report Plugins go here -->
		</reportPlugins>
		<locales>en</locales>
	</configuration>
	<dependencies>
	    <!-- To use the Markdown format -->
		<dependency>
			<groupId>org.apache.maven.doxia</groupId>
			<artifactId>doxia-module-markdown</artifactId>
			<version>${maven.doxia.module.markdown.version}</version>
		</dependency>
	</dependencies>
	</plugin>
  </plugins>
</build>
...

Now add each plugin into the reportPlugins section just as you would any other dependency.

Page Templates

Maven will look for page templates in the src/site directory of the project. If the project is a parent pom project, add the directory src/site to the root of the project.

Here is a sample directory layout:

├── projectA
│   ├── pom.xml
│   └── src
│       ├── main
│       └── test
├── projectB
│   ├── pom.xml
│   └── src
│       ├── main
│       └── test
├── pom.xml
├── src
│   └── site
|       ├── markdown
|       │   ├── build.md
|       │   ├── index.md
|       │   └── services
|       │       └── persistence.md
|       ├── resources
|       │   └── images
|       │       └── technophile.png
|       └── site.xml
└── projectZ
    ├── pom.xml
    └── src
        ├── main
        └── test

Notice that src is at the same level as the top level pom.

Files:
Line 24: site.xml defines the sites layout.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/DECORATION/1.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/DECORATION/1.0.0
  http://maven.apache.org/xsd/decoration-1.0.0.xsd">

  <body>
    <menu name="Overview">
      <item name="Introduction" href="index.html"/>
      <item name="Building MyProject" href="build.html"/>
    </menu>

    <menu name="Common Services">
      <item name="Persistence Detail" href="services/persistence.html"/>
    </menu>

    <menu ref="reports"/>
  </body>
</project>

This generates a page with links for the index page, a build page and a persistence page. Also, line 17: menu ref=”reports” is a special link for the report plugins.

The *.md pages will convert from Markdown format into HTML. The build.md file might contain something like this:

![Technophile](images/technophile.png)

Building Core Spring
==========================

[Gordon Dickens](mailto:gordon@gordondickens.com)

-----

My Project
----------

This project infuses time, space and dimension into a convenient war file.

Line 1 is a reference to an image file. NOTE: this has to be in the site/resources directory.
Line 6 shows how to include a link or hyperlink.

Complete Reporting Config

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-site-plugin</artifactId>
  <version>${maven.site.plugin}</version>
  <executions>
    <execution>
      <id>attach-descriptor</id>
      <goals>
        <goal>attach-descriptor</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
   <reportPlugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-surefire-report-plugin</artifactId>
      <version>${maven.surefire.plugin}</version>
      <configuration>
        <outputDirectory>${project.reporting.outputDirectory}/testresults</outputDirectory>
      </configuration>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-javadoc-plugin</artifactId>
      <version>${maven.javadoc.plugin}</version>
      <configuration>
        <aggregate>true</aggregate>
      </configuration>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-checkstyle-plugin</artifactId>
      <version>${maven.checkstyle.plugin}</version>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-project-info-reports-plugin</artifactId>
      <version>${maven.project.info.reports.plugin}</version>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-jxr-plugin</artifactId>
      <version>${maven.jxr.plugin}</version>
      <configuration>
        <aggregate>true</aggregate>
      </configuration>
    </plugin>
    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>cobertura-maven-plugin</artifactId>
      <version>${maven.cobertura.plugin}</version>
      <configuration>
        <aggregate>true</aggregate>
        <outputDirectory>%{project.reporting.outputDirectory}/cobertura</outputDirectory>
      </configuration>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-pmd-plugin</artifactId>
      <version>${maven.pmd.plugin}</version>
      <configuration>
        <aggregate>true</aggregate>
        <sourceEncoding>${project.build.sourceEncoding}</sourceEncoding>
        <!-- The minimum tokens before a violation -->
        <minimumTokens>100</minimumTokens>
        <!-- Turn off if no xref report -->
        <linkXRef>true</linkXRef>
        <verbose>true</verbose>
        <targetJdk>${java.version}</targetJdk>
        <rulesets>
          <ruleset>/rulesets/maven.xml</ruleset>
          <ruleset>/rulesets/migrating_to_junit4.xml</ruleset>
          <ruleset>/rulesets/design.xml</ruleset>
          <ruleset>/rulesets/unusedcode.xml</ruleset>
          <ruleset>/rulesets/typeresolution.xml</ruleset>
        </rulesets>
      </configuration>
    </plugin>
    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>findbugs-maven-plugin</artifactId>
      <version>${maven.findbugs.plugin}</version>
    </plugin>
    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>versions-maven-plugin</artifactId>
      <version>${maven.versions.plugin}</version>
    </plugin>
    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>taglist-maven-plugin</artifactId>
      <version>${maven.taglist.plugin}</version>
      <configuration>
        <aggregate>true</aggregate>
      </configuration>
    </plugin>
   </reportPlugins>
  <locales>en</locales>
  </configuration>
  <dependencies>
    <dependency>
      <groupId>org.apache.maven.doxia</groupId>
      <artifactId>doxia-module-markdown</artifactId>
      <version>${maven.doxia.module.markdown.version}</version>
    </dependency>
  </dependencies>
</plugin>

Summary

Wow, that’s a lot of config! The configuration sample above has a bit of overlap. Simple remove the report plugins that are not as important to you at the present time.

Watch out for the JXR plugin, this is a very time consuming report to generate. If this becomes something you want to run infrequently, I recommend different Maven profiles, one with JXR and one without.

Posted in Maven | Tagged , , , , , , , , , | Leave a comment

Enterprise Spring Framework Best Practices – Part 3 – XML Config

Enterprise Spring Best Practices Series
In part 3, Spring XML Configuration.

The best thing about Spring is that there are several way to solve a problem, the worst thing about Spring is that there are several ways to solve a problem!

One of the greatest challenges when using Spring is choosing the best way to implement solutions. As most of us developers do, we hit Google or grab books on Spring, which can get us moving in the right direction. Many times we find conflicting configurations between implementation approaches. For Spring newcomers, this can be challenging and cause grievous mental confusion down the road.


Sections




Spring Namespaces


No version numbers in schema references

Instead of:

<?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">
...
</beans>

USE This Config:

<?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.xsd


http://www.springframework.org/schema/context

    http://www.springframework.org/schema/context/spring-context.xsd">
...
</beans>

WHY?
Spring automatically picks the highest version available from the project dependencies (jars). As a project evolves, the Spring version will be updated, we won’t have to maintain all the XML config files to see the new features.



One Bootstrap XML File



There are many examples of using multiple XML configuration files. An application usually has several XML configuration files, but there should only be ONE bootstrap file. This bootstrap file should use the <import resource=""/> to include other config files.



Classpath Prefix



Always use classpath: prefix
When importing resources, XML config, properties, etc. Always use the classpath: or classpath*: prefix.
This provides consistency and clarity to the location of the resource. Not every feature of Spring behaves the same, classpath: guarantees consistency.
The classpath is determined by the build tool and IDE. Usually this is src/main/java for java code, src/main/resources for non-java dependencies and for tests, src/test/java for java code and src/test/resources for non-java resources.

Example:

<import 
  resource="classpath:/META-INF/spring/applicationContext-security.xml"/>



Bean Naming



The Spring Context is the container for the application’s beans. Each bean is uniquely identified by its name. The xml attribute “id” is most commonly used to define the bean’s name. The “id” attribute is great because it is, by XML Law, unique per file.

<bean id="accountService"
  class="com.gordondickens.services.AccountService/>

However, if we want to use special symbols in the name or provide aliases to the name, we can use the Spring provided “name” attribute.

<bean name="accountService,services/account" 
  class="com.gordondickens.services.AccountService/>

Spring 3.1 added the profile feature, providing the ability to configure beans by category or region.
With 3.1, Spring overloads the XML “id” attribute allowing multiple beans with the same “id” in an XML file by profile.

<?xml version="1.0" encoding="UTF-8"?>
<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">

  <beans profiles="dev,qa">
    <bean id="dataSource" class="..."/>
    <bean id="messagingProvider" class="..."/>
  </beans>
  
  <beans profiles="prod">
    <bean id="dataSource" class="..."/>
    <bean id="messagingProvider" class="..."/>
  </beans>
</beans>

For more detail on Spring 3.1 profiles, see my blog Spring 3.1 Environment Profiles



Dependency Injection



Dependency Injection is one of the basic tenets of the Spring Framework. DI provides developers the ability to “wire together” bean relationships in configuration instead of coding the relationships.

The two ways to perform di are either by Constructor injection or Setter Injection.

In Enterprise Spring Best Practices – Part 2 – Application Architecture, describes the layered application approach. In this layered approach, we can expect to inject beans together between layers.
For example, wiring from the bottom up:

  1. DataSource, the common JDBC class for database connectivity, is injected into our persistence beans
  2. The persistence beans are injected into our service beans
  3. The service beans are injected into our controller beans

Constructor Injection

Constructor injection is performed using the <bean/> node <constructor-arg.
Thread safety, is a strong case for using constructors. Making beans immutable, is the cheapest thread-safety we can code.

In the following example, we see configuration of an in-memory HSQLDB database with an “id” of “dataSource”. The bean AccountRepositoryImpl bean is injected with this implementation when Spring starts.

<bean id="accountRepository"
  class="com.gordondickens.repository.internal.AccountRepositoryImpl">
  <constructor-arg ref="dataSource"/>
</bean>

<!-- Spring's In-Memory DB Config, using HSQLDB -->
<!-- Note the HSQLDB driver must be in the project dependencies -->
<jdbc:embedded-database
  id="dataSource" type="HSQL">
  <jdbc:script
    location="classpath:/mySchema.sql"/>
  <jdbc:script
    location="classpath:/mySampleData.sql"/>
</jdbc:embedded-database>

Setter Injection

Setter injection, provides the capability of injecting beans via a setter method. Traditionally, this has been the preferred choice for many developers, because the configuration is easier to read.

<bean id="accountRepository"
      class="com.gordondickens.repository.internal.AccountRepositoryImpl">
  <property name="dataSource" ref="dataSource"/>
</bean>



Third Party Beans



Any Java class can be used in the Spring framework. Infrastructure beans, such as ActiveMQ’s ConnectionFactory or Oracle’s OracleDataSource is possible.

Third party beans, where we don’t have the source, or do not wish to tamper with the source, the choice for DI is made for us.



Externalize Properties



Deployment configuration requires setting environmental parameters, such as database connection properties.

Since XML can be brittle, it is best to externalize settings into property files. This makes it easier for the deployment team to change resource configuration with less risk.

Spring provides a PropertyPlaceholderConfigurer for that purpose.

Property Replacement Config

<context:property-placeholder
  location="classpath*:META-INF/spring/*.properties"/>

<bean id="dataSource"
  class="org.apache.commons.dbcp.BasicDataSource"
  destroy-method="close">
  <property name="driverClassName"
    value="${database.driverClassName}"/>
  <property name="url"
    value="${database.url}"/>
  <property name="username"
    value="${database.username}"/>
  <property name="password"
    value="${database.password}"/>
</bean>

Properties File

database.driverClassName=org.hsqldb.jdbcDriver
database.url=jdbc\:hsqldb\:mem\:mydb
database.username=sa
database.password=



Logging Beans



Following up on Enterprise Spring Best Practices – Part 1 – Project Configuration logging configuration.

Java Util Logging

To Enable handling of java.util.logging classes with SLF4J. Register the following in your Spring configuration:

<!-- Enable handling of java.util.logging through SLF4J -->
<bean id="slf4JBridgeHandler" class="org.slf4j.bridge.SLF4JBridgeHandler"
  init-method="removeHandlersForRootLogger"/>
<bean class="org.slf4j.bridge.SLF4JBridgeHandler"
  init-method="install"
  depends-on="slf4JBridgeHandler"/>

System.out and System.err

To Enable handling of System.out and System.err messages. Register the following in your Spring configuration:

NOTE: This is NOT recommended for ongoing development, but for migrating poor code to use logging.

<!-- System.out.println & System.err.println handling through SLF4J -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
  <property name="targetClass" value="uk.org.lidalia.sysoutslf4j.context.SysOutOverSLF4J"/>
  <property name="staticMethod"
      value="uk.org.lidalia.sysoutslf4j.context.SysOutOverSLF4J.sendSystemOutAndErrToSLF4J"/>
  <property name="arguments">
    <list>
      <!-- Set log level for System.out -->
      <util:constant 
        static-field="uk.org.lidalia.sysoutslf4j.context.LogLevel.DEBUG"/>
      <!-- Set log level for System.err -->
      <util:constant
        static-field="uk.org.lidalia.sysoutslf4j.context.LogLevel.ERROR"/>
    </list>
  </property>
</bean>

Maven Dependency for SysOutOverSLF4J

<dependency>
  <groupId>uk.org.lidalia</groupId>
  <artifactId>sysout-over-slf4j</artifactId>
  <version>1.0.2</version>
</dependency>



Best Practices


  • DO NOT use version numbers with the Spring schema namespaces
  • Always use classpath:/ prefix for consist resource referencing
  • Always use a single XML config file to bootstrap the application or tests
  • Use the XML “id” attribute to identify a bean
  • Use Constructor injection to promote thread safety
  • Use Properties for configurable resources
  • DO NOT use the SysOutOverSLF4J for anything other than migration



Further Reading




Social Me



Twitter – twitter.com/gdickens
LinkedIn – linkedin.com/in/gordondickens
GitHub: github.com/gordonad
gordon@gordondickens.com


Posted in Java Util Logging, SLF4J, Spring | Tagged , , , , , , , | 8 Comments

Mac OSX Mountain Lion – Git SVN Error

I ran into this issue just after upgrading to Mac OSX Mountain Lion 10.8

Can't locate SVN/Core.pm in @INC (@INC contains: 
/Applications/Xcode.app/Contents/Developer/usr/share/git-core/perl 
/usr/../Library/Perl/5.12/darwin-thread-multi-2level 
/usr/share/git-core/perl /Library/Perl/5.12/darwin-thread-multi-2level 
/Library/Perl/5.12 /Network/Library/Perl/5.12/darwin-thread-multi-2level 
/Network/Library/Perl/5.12 /Library/Perl/Updates/5.12.4 
/System/Library/Perl/5.12/darwin-thread-multi-2level 
/System/Library/Perl/5.12 /System/Library/Perl/Extras/5.12/darwin-thread-multi-2level 
/System/Library/Perl/Extras/5.12 .) at /usr/libexec/git-core/git-svn line 61.

I found this blog: http://lifeandcode.net/2012/02/using-git-svn-on-os-x-10-8-developer-preview/

1. Update to XCode 4.4!
2. Add this to your shell script

export PERL5LIB="/Applications/Xcode.app/Contents/Developer/Library/Perl/5.12/darwin-thread-multi-2level"

UPDATE: 28-Jul-12

  • Install XCode Command Line Tools
  • Run this command: sudo ln -s /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.8.xctoolchain

UPDATE: 30-Jul-12

Issue with installing MariaDB (better fork of MySql). This link indicates a similar issue with Graphwiz.
ERROR: "fatal error: 'ac_nonexistent.h' file not found"

  • export HOMEBREW_MAKE_JOBS=1
  • brew install -vd mariadb

Posted in 10.8, Apple, HomeBrew, Mountain Lion, OSX | Tagged , , , , , , , , , , , , , , , , | Leave a comment

Enterprise Spring Best Practices – Part 2 – Application Architecture

In part 2, Application Architecture.

This blog presents a look at the overall application components and architecture.


Sections




Application Domains



Our application components break down into two fundamental categories, the System and Problem Domains.

  • System Domain – infrastructure components, the plumbing, this is Spring’s sweet spot!
  • Problem Domain – business components, typically use-case driven, this is what most of developers are paid to solve



Application Layers



Application components (beans) should be separated into distinct layers, and categories.





Bean Layers
  1. Controllers (for MVC, System Domain)
  2. Services (Problem Domain)
  3. Repository (System Domain)
Other Bean Categories
  • Data Transfer Objects (Problem Domain)
  • System Functions (System Domain)



Controller Beans



More on Controllers in an upcoming blog on Enterprise Spring Best Practices MVC blog – TBD



Service Beans



Service Beans are Problem Domain components. These are the MOST significant in the application. Service beans are the Fundamental component of SOA.

  • These are POJOs
  • Always defined from interfaces
  • NEVER include infrastructure components
  • NO import of Spring or utility libraries
  • NO infrastructure annotations
  • Always declare transaction boundaries by public functions
  • Create implementation/concrete classes in a sub-package named internal

Spring annotations can be very useful for services, useful annotations are @Service and @Transactional. To abstract away the infrastructure from the business services, create a project specific meta annotation.

Custom Meta Annotation
package com.gordondickens.service.annotation;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Service
@Transactional
public @interface AppService {
    String value() default "";
}
Meta Annotation Use
...
@AppService
public class MyClass() {
  ...
}



Repository Beans



Repository beans are in the System Domain. More on this in Enterprise Spring Best Practices ORM blog – TBD

  • DO NOT contain business logic
  • Do use Spring and JPA annotations
  • Should be considered disposable



Data Transfer Beans



Data Transfer Objects (DTO) are the fundamental objects in and out of our system. DTOs are simple public POJOs that receive and send data as a logical set.

  • Always Public Beans
  • Annotate with JAXB2 Annotations



Conversion Beans



Spring provides a rich conversion registry at it’s core. The conversion service in Spring is based on the original Bean Specification PropertyEditor.

PropertyEditors are focussed on String data into and out of our application.

The Spring class org.springframework.beans.PropertyEditorRegistrySupport shows the built in String <–> object classes. Which we use, usually without knowledge, in our applications. When we configure our applications with XML and send in property values, Spring uses reflection to determine the argument type, if that type is not a String, Spring looks for a PropertyEditor that can convert from String to the target type. We also can create our own PropertyEditor’s and register them for types such as US Social Security Number or Telephone Number. See: Craig Wall’s Spring in Action, 3rd Ed for examples.

  • Primitive wrapper types: Long, Integer, etc
  • Collection types: List, Property, Set, Map, etc.
  • Arrays
  • Utility types: URL, TimeZone, Locale, etc.

Spring 3.0 introduced the Conversion service providing us the ability to register a conversion service for object <–> other conversion. To use the conversion registry, we can register a conversion class that will automatically convert to/from MyObject <–> MyOtherObject. See Using Spring Customer Type Converter Blog.



Further Reading




Social Me



Twitter – twitter.com/gdickens
LinkedIn – linkedin.com/in/gordondickens
GitHub: github.com/gordonad
gordon@gordondickens.com


Posted in Spring, Spring Framework | Tagged , , , , | 3 Comments

Enterprise Spring Best Practices – Part 1 – Project Config

Enterprise Spring Best Practices Series
In part 1, let’s review project structure and configuration.


Sections




Project Directories


Production
  • src/main/java – Java Source code packages and classes
  • src/main/resources – NON-Java Resources, such as property files and Spring configuration
Test
  • src/test/java – Test Source code packages and classes
  • src/test/resources – NON-Java Resources, such as property files and Spring configuration

Project Structure Example

── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── gordondickens
    │   │           └── sample
    │   │               ├── domain
    │   │               │   └── MyDomain.java
    │   │               ├── repository
    │   │               │   └── MyDomainRepository.java
    │   │               ├── service
    │   │               │   ├── MyDomainService.java
    │   │               │   └── internal
    │   │               │       └── MyDomainServiceImpl.java
    │   │               └── web
    │   │                   └── MyDomainController.java
    │   ├── resources
    │   │   ├── META-INF
    │   │   │   └── spring
    │   │   │       ├── applicationContext.xml
    │   │   │       └── database.properties
    │   │   ├── logback-access.xml
    │   │   └── logback.xml
    │   └── webapp
    │       ├── WEB-INF
    │       │   ├── classes
    │       │   ├── i18n
    │       │   ├── layouts
    │       │   ├── spring
    │       │   │   └── webmvc-config.xml
    │       │   ├── views
    │       │   │   ├── myDomain
    │       │   │   │   ├── create.jsp
    │       │   │   │   ├── list.jsp
    │       │   │   │   ├── show.jsp
    │       │   │   │   └── update.jsp
    │       │   │   ├── dataAccessFailure.jsp
    │       │   │   ├── index.jsp
    │       │   │   ├── resourceNotFound.jsp
    │       │   │   ├── uncaughtException.jsp
    │       │   │   └── views.xml
    │       │   └── web.xml
    │       ├── images
    │       └── styles
    ├── site
    │   ├── apt
    │   ├── fml
    │   ├── site.xml
    │   └── xdoc
    └── test
        ├── java
        │   └── com
        │       └── gordondickens
        │           └── sample
        │               └── service
        │                   └── MyDomainServiceTests.java
        └── resources
            ├── com
            │   └── gordondickens
            │       └── sample
            │           └── service
            │               └── MyDomainServiceTests-context.xml
            └── logback-test.xml



Project Dependencies



I am a big fan of Maven, it provides a consistent build structure and numerous plugins. Gradle is emerging as an alternative Groovy-based build tool, which supports the Maven structure. If you are still using Ant, I urge you to move to a more robust build tool such as Maven or Gradle. One of the challenges of enterprise build tools is managing transitive dependencies, here are some recommendations to ease these challenges.

Dependency Versions
  • DO NOT put version numbers below the <properties/> section, this will make it easier to upgrade and test newer versions.
  • DO include version numbers for ALL plugins! Do not rely on Maven’s built in Super Pom plugin versions!
Dependency Management
  • USE Maven’s <DependencyManagement> section to control implicit and explicit versions! Transitive dependencies will be resolved by those included in this section.
Enforcer Plugin

Prohibit the direct or indirect inclusion of incompatible and/or legacy jars. For example, SLF4J 1.5, 1.6 and SLF4J 1.7 do not work together, therefore we need to prohibit the project from building with mixed dependency versions. Spring is used by many open source projects, some reference older versions of Spring jars, so we want to control which Spring jar versions are inluded in our build.

Enforcer Example

  • Ensures Java 1.6
  • Ensures Maven 2.2.1 to 3.0.x
  • Ensures Spring Jars 3.1 or greater
  • Prohibits old javassist, should be org.javassist
  • Ensures no commons-logging or commons-logging-api dependencies
  • Ensures no log4j dependencies
  • Ensures no SLF4J 1.5 or 1.6 dependencies
  • Prohibits old hsqldb, should be org.hsqldb
  • Prohibits old aspectj, should be org.aspectj
<properties>
...
  <java.version>1.6</java.version>
...
  <maven.enforcer.plugin>1.2</maven.enforcer.plugin>
  <maven.version.range>[2.2.1,3.1.0)</maven.version.range>
...
</properties>

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-enforcer-plugin</artifactId>
  <version>${maven.enforcer.plugin}</version>
  <executions>
    <execution>
      <id>enforce-banned-dependencies</id>
      <goals>
        <goal>enforce</goal>
      </goals>
      <configuration>
        <rules>
          <bannedDependencies>
            <searchTransitive>true</searchTransitive>
            <excludes>
              <exclude>javassist:javassist</exclude>
              <exclude>commons-logging</exclude>
              <exclude>aspectj:aspectj*</exclude>
              <exclude>hsqldb:hsqldb</exclude>
              <exclude>log4j:log4j</exclude>
              <exclude>org.slf4j:1.5*</exclude>
              <exclude>org.springframework:2.*</exclude>
              <exclude>org.springframework:3.0.*</exclude>
            </excludes>
          </bannedDependencies>
          <requireMavenVersion>
            <version>${maven.version.range}</version>
          </requireMavenVersion>
          <requireJavaVersion>
            <version>${java.version}</version>
          </requireJavaVersion>
        </rules>
        <fail>true</fail>
      </configuration>
    </execution>
  </executions>
</plugin>



Smart Logging


  • NEVER use System.out
  • NEVER use System.err
  • ALWAYS use SLF4J
  • ALWAYS use Logback
  • Prohibit Apache Commons Logging (JCL) aka Jakarta Commons Logging
  • Prohibit Java Util Logging (JUL)

Classes that use logging should include the following config for SLF4J (not log4j, not jcl, not jul, not logback):

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
...
public class MyClass {
  private static final Logger logger =
    LoggerFactory.getLogger(MyClass.class);
...
}

In the example below, SLF4J provides jars to route JCL and JUL logging through jcl-over-slf4j and jul-to-slf4j. Spring uses JCL, so we need to use jcl-over-slf4j to handle Spring specific logged messages.

<properties>
...
  <logback.version>1.0.10</logback.version>
...
  <slf4j.version>1.7.4</slf4j.version>
...
</properties>

...

<dependencies>
...
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jcl-over-slf4j</artifactId>
  </dependency>
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jul-to-slf4j</artifactId>
  </dependency>
  <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
  </dependency>
...
</dependencies>

...

<dependencyManagement>
  <dependencies>
...
   <!-- Logging with SLF4J & LogBack -->
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jcl-over-slf4j</artifactId>
    <version>${slf4j.version}</version>
  </dependency>
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>${slf4j.version}</version>
  </dependency>
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jul-to-slf4j</artifactId>
    <version>${slf4j.version}</version>
  </dependency>
  <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>${logback.version}</version>
  </dependency>
  <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>${logback.version}</version>
  </dependency>
  <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-access</artifactId>
    <version>${logback.version}</version>
  </dependency>
...
  </dependencies>
</dependencyManagement>
Logging Configuration Files
  • src/main/resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>

  <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
    <resetJUL>true</resetJUL>
  </contextListener>

  <!-- To enable JMX Management -->
  <jmxConfigurator/>

  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%.-1level|%-40.40logger{0}|%msg%n</pattern>
    </encoder>
  </appender>

  <logger name="com.mycompany.myapp" level="debug" />
  <logger name="org.springframework" level="info" />

  <logger name="org.springframework.beans" level="debug" />

  <root level="warn">
    <appender-ref ref="console" />
  </root>
</configuration>


  • src/main/resources/logback-test.xml

Same configuration as production code, that will only be used for tests, usually for adding more log detail.


  • src/main/resources/logback-access.xml

Configuration for server access logs. HTTPRequest and HTTPResponses messages can be displayed and/or logged When used with Logback TeeFilter in web.xml – GREAT for RESTful testing.

NOTE: Using ${user.dir}, the log files will be created in the root of the project. We will want to configure this differently for production.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />

  <filter class="ch.qos.logback.access.filter.CountingFilter">
    <name>countingFilter</name>
  </filter>

  <appender name="accessfile" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${user.dir}/logs/app-access.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>${user.dir}/logs/app-access.%d{yyyy-MM-dd}.log.zip</fileNamePattern>
    </rollingPolicy>

    <encoder>
        <pattern>combined</pattern>
    </encoder>
  </appender>

  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%n%fullRequest%n%fullResponse%n</pattern>
    </encoder>
  </appender>

  <appender name="reqrespfile" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${user.dir}/logs/app-req-resp.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <fileNamePattern>${user.dir}/logs/app-req-resp.%d{yyyy-MM-dd}.log.zip</fileNamePattern>
    </rollingPolicy>

    <encoder>
      <pattern>%n%fullRequest%n%fullResponse%n</pattern>
    </encoder>
  </appender>

  <appender-ref ref="accessfile" />
  <appender-ref ref="reqrespfile" />
  <appender-ref ref="console" />
</configuration>

See Enterprise Spring Best Practices – XML Configuration – Part 3 for Spring configuration of java.util.logging and System.out, System.err handlers for SLF4J.



Running with Jetty and Tomcat



Developers can run Jetty or Tomcat for testing with the following Maven plugin configuration. The plugin configuration below configures the servers for JMX, SLF4J, Logback and Logback Access.

Running Jetty
    $ mvn clean install jetty:run
Running Tomcat 7
    $ mvn clean install tomcat7:run

NOTE: DO NOT use tomcat:run, this is the old Tomcat plugin.

<properties>
...
  <maven.jetty.plugin>8.1.10.v20130312</maven.jetty.plugin>
...
  <maven.tomcat.plugin>2.1</maven.tomcat.plugin>
...
</properties>

...

<plugins>
...
  <plugin>
  <groupId>org.apache.tomcat.maven</groupId>
  <artifactId>tomcat7-maven-plugin</artifactId>
  <version>${maven.tomcat.plugin}</version>
  <configuration>
    <systemProperties>
    <com.sun.management.jmxremote>true</com.sun.management.jmxremote>
    <com.sun.management.jmxremote.port>8050</com.sun.management.jmxremote.port>
    <com.sun.management.jmxremote.ssl>false</com.sun.management.jmxremote.ssl>
    <com.sun.management.jmxremote.authenticate>false</com.sun.management.jmxremote.authenticate>
    <java.util.logging.manager>org.apache.juli.ClassLoaderLogManager</java.util.logging.manager>
    <logback.ContextSelector>JNDI</logback.ContextSelector>
  </systemProperties>
  </configuration>
  <dependencies>
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jcl-over-slf4j</artifactId>
    <version>${slf4j.version}</version>
    <scope>runtime</scope>
  </dependency>
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>${slf4j.version}</version>
    <scope>runtime</scope>
  </dependency>
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jul-to-slf4j</artifactId>
    <version>${slf4j.version}</version>
    <scope>runtime</scope>
  </dependency>
  <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>${logback.version}</version>
    <scope>runtime</scope>
  </dependency>
  <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-access</artifactId>
    <version>${logback.version}</version>
    <scope>runtime</scope>
  </dependency>
  </dependencies>
  </plugin>
  <plugin>
    <groupId>org.mortbay.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <version>${maven.jetty.plugin}</version>
    <configuration>
      <webAppConfig>
        <contextPath>/${project.name}</contextPath>
      </webAppConfig>
      <stopPort>9966</stopPort>
      <stopKey>shutterdown</stopKey>
      <requestLog implementation="ch.qos.logback.access.jetty.RequestLogImpl">
        <fileName>./src/main/resources/logback-access.xml</fileName>
      </requestLog>
      <systemProperties>
        <systemProperty>
          <name>logback.configurationFile</name>
          <value>./src/main/resources/logback.xml</value>
        </systemProperty>
        <systemProperty>
          <name>com.sun.management.jmxremote</name>
          <value>true</value>
        </systemProperty>
        <systemProperty>
          <name>com.sun.management.jmxremote.port</name>
          <value>8050</value>
        </systemProperty>
        <systemProperty>
          <name>com.sun.management.jmxremote.ssl</name>
          <value>false</value>
        </systemProperty>
        <systemProperty>
          <name>com.sun.management.jmxremote.authenticate</name>
          <value>false</value>
        </systemProperty>
      </systemProperties>
    </configuration>
    <dependencies>
      <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <version>${slf4j.version}</version>
        <scope>runtime</scope>
      </dependency>
      <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${slf4j.version}</version>
        <scope>runtime</scope>
      </dependency>
      <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jul-to-slf4j</artifactId>
        <version>${slf4j.version}</version>
        <scope>runtime</scope>
      </dependency>
      <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>${logback.version}</version>
        <scope>runtime</scope>
      </dependency>
      <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-access</artifactId>
        <version>${logback.version}</version>
        <scope>runtime</scope>
      </dependency>
    </dependencies>
  </plugin>
...
</plugins>
Logback web.xml Helpers

To see Logback status, optionally add the following Logback Status servlet.

...
  <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>/logbackStatus</url-pattern>
  </servlet-mapping>
...

To capture the HTTPRequest and HTTPResponse data use the Logback Tee Filter.

...
  <filter>
    <filter-name>TeeFilter</filter-name>
    <filter-class>ch.qos.logback.access.servlet.TeeFilter</filter-class>
  </filter>

  <filter-mapping>
    <filter-name>TeeFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
...



Spring Configuration Files



Be consistent with naming Spring xml configuration files. Start all files with the same name such as applicationConfig*.xml.

For example: applicationConfig-bootstrap.xml, applicationConfig-jpa.xml, applicationConfig-security.xml, etc.

In the next blog, I will discuss Enterprise Spring configuration best practices.

Config Directories
  • src/main/resources/META-INF/spring – Spring XML configuration directory
  • src/main/webapp/WEB-INF/spring – Spring MVC configuration directory



Complete Maven Config



The Best Practices Maven Config file is tuned for Spring application dependencies, reporting and plugin support.

Features of the Best Practices Maven Config file:

  • All versions in properties section
  • Dependency Management section controls transitive dependencies
  • All plugins defined with versions in Plugin Management section
  • Enforcer plugin stops build for incompatible dependencies
  • Maven Site plugin configured for reporting, with common reporting plugins
  • Eclipse plugin uses new Eclipse brand Maven plugin, formerly Sonatype’s
  • Idea (IntelliJ) plugin, is obsolete – not included
  • Versions plugin to check for dependency and plugin updates

BEST Practices Maven Config File



Valuable Maven Commands


Display Dependency Updates
    $ mvn versions:display-dependency-updates
Display Plugin Updates
    $ mvn versions:display-plugin-updates
Display Dependency Tree
    $ mvn dependency:tree -Ddetail
Display Dependency List
    $ mvn dependency:list
Display Effective POM
    $ mvn help:effective-pom
Display Project Settings
    $ mvn help:effective-settings
Display System and Environment Variables
    $ mvn help:system
Display Build Class Path
    $ mvn dependency:build-classpath



Further Reading




Social Me



Twitter – twitter.com/gdickens
LinkedIn – linkedin.com/in/gordondickens
GitHub: github.com/gordonad
gordon@gordondickens.com


Posted in Eclipse, Jakarta Commons Logging, Java, Java Util Logging, Jetty, Log4J, LogBack, Logging, Maven, SLF4J, Spring, Spring Framework, Spring MVC, STS, Testing, Tomcat | Tagged , , , , , , | 10 Comments

Gemini Blueprint – Converting from Spring OSGi

Eclipse Virgo OSGi Enthusiasts, like myself, can now switch from the Spring OSGi namespace to the Eclipse Gemini Blueprint namespaces for bundles.


Maven Dependencies

<!-- Gemini Blueprint OSGi -->
<properties>
  <gemini.blueprint.version>1.0.0.RELEASE</gemini.blueprint.version>
</properties>
...

<dependency>
  <groupId>org.eclipse.gemini</groupId>
  <artifactId>org.eclipse.gemini.blueprint.extender</artifactId>
  <version>${gemini.blueprint.version}</version>
  <exclusions>
    <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>org.springframework.beans</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>org.springframework.core</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>org.springframework.context</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>org.eclipse.gemini.blueprint</groupId>
  <artifactId>gemini-blueprint-mock</artifactId>
  <version>${gemini.blueprint.version}</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.eclipse.gemini</groupId>
  <artifactId>org.eclipse.gemini.blueprint.core</artifactId>
  <version>${gemini.blueprint.version}</version>
  <exclusions>
    <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>org.springframework.aop</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>org.springframework.beans</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>org.springframework.core</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>org.springframework.context</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>org.eclipse.gemini</groupId>
  <artifactId>org.eclipse.gemini.blueprint.io</artifactId>
  <version>${gemini.blueprint.version}</version>
</dependency>


Repositories

<repository>
  <id>com.springsource.repository.bundle.external</id>
  <name>SpringSource Enterprise Bundle Repository - External Bundle Releases</name>
  <url>http://repository.springsource.com/maven/bundles/external</url>
</repository>


Eclipse Gemini Blueprint Config

XML Tag Attributes Description
<bean /> id, activation, depends-on, class, init-method, destroy-method, factory-method, factory-ref, scope The type definition for a component. The bean’s attributes provide the characteristics for how to create the bean instance. Constructor arguments and injected properties are specified via child <argument> and <property> elements
<blueprint /> default-activation, default-timeout, default-availability, The root element for a blueprint configuration file with two sections. The first section (contained within the <type-converters> element) identifies components that are used for converting values into different target types. The type converters are optional. The second section contains component definitions. Components are <bean>, <service>, <reference>, and <reference-list> elements that identify the bundle components that will be managed by the blueprint service
<description />   A generic element type to allow documentation to be added to the blueprint configuration
<compendium:cm-properties /> id, persistent-id, local-override, dynamic, init-lazy, init-timeout Exposes the properties found in the Configuration Admin service under the given <persistent-id>
<compendium:managed-properties /> persistent-id, autowire-on-update, update-method Defines a bean based on the given class name and configuration, with properties autowired-by-name based on the configuration stored under the given <persistent-id>
<compendium:managed-service-factory /> auto-export, autowire-on-update, context-class-loader, depends-on, factory-pid, interface, update-method Defines a collection of beans based on the given class name, with properties <autowired-by-name> based on the configuration sets stored under the given factory <persistent-id>
<ref /> component-id Defines a required <component-id> for the reference component
<reference /> id, activation, depends-on, interface, filter, component-name, availability Defines the instances of a registered <service>, with a <timeout>. If the <timeout> is not specified, the <default-timeout> value is inherited from the encapsulating <blueprint> definition
<reference-list /> id, activation, depends-on, interface, filter, component-name, availability, member-type Builds in the characteristics of the <service> type to define characteristics of the <reference-list>. This adds in the characteristics that only apply to collections of references via <member-type>. Subnodes can be <description >, <compendium:cm-properties >, <compendium:managed-properties >, <compendium:managed-service-factory >, <reference-listener >
<reference-listener /> ref, bind-method, unbind-method A definition of a listener that will watch for bind/unbind events associated with the <service> reference. The listener can be a <ref> to a <bean> or <reference> element, or an inline <bean> or <reference>
<service /> id, activation, depends-on, interface, ref, auto-export, ranking Defines the type for services exported by this blueprint bundle. Services are sourced by either a <ref> to a <bean> component or an <inline> bean component
<type-converters />   Defines a set of <bean>, <ref>, or <reference> elements that identify the type converter components

Examples

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0
    http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"
  default-activation="eager">

  <!-- import the DataSource from OSGi -->
  <reference id="dataSource" interface="javax.sql.DataSource"/>

  <!-- export the directory bean to OSGi under the Directory interface -->
  <service ref="directory" interface="greenpages.Directory"/>
</blueprint>


<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:compendium="http://www.eclipse.org/gemini/blueprint/schema/blueprint-compendium"
  xsi:schemaLocation="http://www.eclipse.org/gemini/blueprint/schema/blueprint-compendium

http://www.eclipse.org/gemini/blueprint/schema/blueprint-compendium/gemini-blueprint-compendium.xsd


http://www.osgi.org/xmlns/blueprint/v1.0.0

  http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"
  default-activation="eager">

  <compendium:cm-properties id="database.props"
    persistent-id="greenpages.db.config"/>

  <!-- Export the JDBC DataSource with the Service Name 'dataSource' -->
  <service ref="dataSource" interface="javax.sql.DataSource"/>
</blueprint>


Resources



Posted in Blueprint, Eclipse, Gemini, Java, OSGi, Spring, Virgo | Tagged , , , , , , | Leave a comment

SpringSource Tool Suite FAQ

Eclipse is one of the most popular IDEs for Java & Spring application development. Spring has developed the Spring IDE plugin providing developers with Spring aware tooling for our projects.

SpringSource Tool Suite = {
   Eclipse + SpringIDE + M2Eclipse +
   GroovyEclipse + AJDT + EMF + WTP + DTP,
   more...
}


Why use STS/SpringIDE

  • Bean Configuration Editor – Content Sensitive bean editing. Defining beans in XML will give you the names of the properties when entering property values in XML. Multitab editor with tabs for Namespaces and namespace specific content (JDBC, Integration, etc).
  • Beans Graph / Dependency Graph – visualizer for Spring config files & config sets
  • Beans Cross Reference View – show bean references across multiple config files
  • Beans Quick Cross Reference – cross ref info on beans in open config file
  • Beans Quick Outline – outline of beans & properties in open config file
  • Spring Beans Searching – by name, id, class, pointcut, etc.
  • Spring Bean Validation – see: Preferences > Spring > Project Validators
  • Spring MVC Request Mappings View – discovers all MVC annotations
  • Java Editor Enhancements – Predefined shortcuts for Spring features, such as “POST” - in a controller will provide a controller method signature. Quick fixes for missing annotations, etc.
  • Visualization – Graphical editors for Beans & Bean relationships, Spring Web Flow, Spring Batch, Spring Integration & Spring Aspects/AOP. Not just for show but editable too!
  • Spring Explorer – Ever wondered… where are my bean config files? Switch to Spring Explorer view to see the beans for the project.


First Things

[or]


What else is in the Box?

  • Groovy/Grails Support
  • Spring OSGi (Dynamic Modules/Eclipse Blueprint) Support
  • Spring dm Server / Eclipse Virgo Support
  • Spring Roo Support
  • Gradle Support
  • tcServer & Insight
  • JDBC Support
  • UML Diagramming

FAQ

Q: Spring features not showing up in my project, what do I do?
A: Right click on the project, under “Spring Tools…” click “Add Spring Project Nature”

Q: Why does Spring Explorer not show any bean config (XML) files?
A: Right click on the project, select “Properties” – In the properties dialog, Spring > Beans Support – click the “Scan…” button.

Q: I imported a project but the red exclamation is over the icon?
A: If it is a Maven project, Right click on the project > Maven > Enable Dependency Management

Q: Why doesn’t Spring find my configuration files when I run my JUnit tests?
A: When using Maven, you need to run “process-resources” or “resources:resources”. Open Preferences > Maven and in the field “Goals to Run when updating project configuration” should have one of these values. Then right click on the project, choose Run As > Maven package [or] Maven Install

Q: Which version of Maven is STS running?
A: Check in Preferences > Maven > Installations – Eclipse Helios & Indigo will by default install an OLD version of Maven 3.0. It is recommended that you install a current release (3.0.3 at the time of this writing) and Add that to the installation list.

Q: How do I open the Maven pom file in XML mode instead of the GUI mode?
A: Preferences > Maven > POM Editor > check “Open XML page in the POM editor by default”

Q: How do I set AOP visualization to recognize my Spring Aspects?
A: Preferences > Visualiser > Check “Spring AOP Provider” in the “Available Providers” box.

Q: I do not write Aspects, why should I care about Aspect Visualization?
A: Even if you do not write your own aspects, Spring implements them via some annotations such as @Transactional

Q: What does the Spring Tools > Enable Spring Aspects tooling do?
A: Enables advanced JDT features – see: wiki.eclipse.org/JDT_weaving_features

Q: What do the letters “S”, “M”, “Aj”, etc mean over my project, directory and files in Eclipse?
A: “S” – Spring, “M” – Maven. “AJ” – AspectJ, “J” – Java

Q: What is the AOP Event Trace View?
A: This view shows what Spring is doing when build it’s internal AOP bean model.



Posted in Grails, Java, OSGi, Roo, Spring, Spring Batch, Spring Framework, Spring Integration, Spring Roo | Tagged , , , , , , , , , , , , , , , , , , , , | 1 Comment