<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Integrating Stuff</title>
	<atom:link href="http://www.integratingstuff.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.integratingstuff.com</link>
	<description>A blog about integrating Java frameworks and third-party APIs with each other.</description>
	<lastBuildDate>Mon, 15 Apr 2013 02:00:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Java2JPA: automatically create JPA Mappings for a Java domain model</title>
		<link>http://www.integratingstuff.com/2013/04/15/java2jpa-automatically-create-jpa-mappings-for-a-java-domain-model/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=java2jpa-automatically-create-jpa-mappings-for-a-java-domain-model</link>
		<comments>http://www.integratingstuff.com/2013/04/15/java2jpa-automatically-create-jpa-mappings-for-a-java-domain-model/#comments</comments>
		<pubDate>Mon, 15 Apr 2013 02:00:03 +0000</pubDate>
		<dc:creator>Steffen Luypaert</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[JPA]]></category>
		<category><![CDATA[Persistence]]></category>

		<guid isPermaLink="false">http://www.integratingstuff.com/?p=724</guid>
		<description><![CDATA[A project I worked on involved creating <a href="http://en.wikipedia.org/wiki/Java_Persistence_API">JPA</a> mappings for different Java POJO domain models.
Since I could not find a tool to automatically create JPA mappings for these models, I created a Java2JPA tool myself.
This post introduces this tool and describes how to use it.]]></description>
			<content:encoded><![CDATA[<p>A project I worked on involved creating <a href="http://en.wikipedia.org/wiki/Java_Persistence_API">JPA</a> mappings for different Java POJO domain models.<br />
Since I could not find a tool to automatically create JPA mappings for these models, I created a Java2JPA tool myself.<br />
This post introduces this tool and describes how to use it.</p>
<h1>Introduction</h1>
<p>The existing Java POJO domain models I needed to create jpa mappings for contained about 20-50 classes each.<br />
Creating these mappings manually would have been a lot of work, so I looked into creating these automatically.<br />
I did not expect to find a complete out-of-the-box solution, but I expected to find something that would enable me to avoid all the repetitive work.<br />
However, I did not find any Java2JPA tool, so I wrote a simple mapping generator myself. </p>
<div class="is_note">
Note: Since the domain models to map, packaged in jars, are also used within Android apps, we preferred using JPA mappings over JPA annotations.<br />
The generator I made only generates JPA Xml mappings and does not annotate existing classes with JPA annotations.<br />
However, someone could implement another JpaMappingRenderer implementation that writes out JPA annotated java files instead of JPA mapping xml files.
</div>
<h1 style="padding-top: 10px;">Generation of the mappings is not entirely automatable</h1>
<p>There is probably no known Java2JPA tool because the mapping process is not entirely automatable.<br />
Whereas popular ddl2jpa and jpa2java tools exist for most JPA Providers(Hibernate Tools for Hibernate, Eclipselink JPA Extensions,..), that provide complete &#8220;generate with the press of a button&#8221; output, java2jpa tools don&#8217;t exist probably because using them would usually require some manual work.<br />
Human decisions need to be made while mapping.<br />
For example, it is not possible to determine the field or combination of fields that represent the database id of a class by plain introspection, and it is also not possible to determine whether an abstract class should be mapped as a &#8220;mapped superclass&#8221; or as an entity that already has its own table.</p>
<h1>The java2jpa tool code</h1>
<p>The code is hosted at <a href="https://github.com/IntegratingStuff/java2jpa">Github(java2jpa)</a>. <a href="https://github.com/IntegratingStuff/java2jpa/archive/master.zip">The code can be downloaded as a zip.</a> You can build the code with Maven.<br />
The code is build around a few core classes: Java2JpaMappingGenerator, RenderJpaMappingForClassStrategy and JpaMappingRenderer.<br />
The Java2JpaMappingGenerator is the class responsible for generating the mappings and has two important fields: a JpaMappingRenderer and a RenderJpaMappingForClassStrategy.<br />
The RenderJpaMappingForClassStrategy is responsible for making the rendering decisions &#8211; e.g. which field will be mapped as id, how class inheritance will be mapped,.. &#8211; and the JpaMappingRenderer is responsible for rendering the actual files based on the rendering decisions made.<br />
To use the tool efficiently more often than not a custom implementation of RenderJpaMappingForClassStrategy is required.</p>
<h1>Basic usage of the code</h1>
<p>In this basic usage example we will generate a jpa mapping for the following two pojo classes in the com.test.model.simple package: Student and Course.<br />
In the unit tests of the source code an example with a more extended sample model is available.</p>
<pre class="is_code">
public class Course {

  private Long id;
  private String title;
  private List&lt;Student&gt; students = new ArrayList&lt;Student&gt;();

  public Long getId() {
    return id;
  }
  public void setId(Long id) {
    this.id = id;
  }
  public String getTitle() {
    return title;
  }
  public void setTitle(String title) {
    this.title = title;
  }
  public List&lt;Student&gt; getStudents() {
    return students;
  }
  public void setStudents(List&lt;Student&gt; students) {
    this.students = students;
  }

}

public class Student {

  private int studentId;
  private String name;
  private Date birthDate;
  private Course course;

  public int getStudentId() {
    return studentId;
  }
  public void setStudentId(int studentId) {
    this.studentId = studentId;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public Date getBirthDate() {
    return birthDate;
  }
  public void setBirthDate(Date birthDate) {
    this.birthDate = birthDate;
  }
  public Course getCourse() {
    return course;
  }
  public void setCourse(Course course) {
    this.course = course;
  }
}
</pre>
<p>Make sure the java2jpa jar is available on the Java classpath.<br />
Then execute the following code:</p>
<pre class="is_code">
Java2JpaMappingGenerator java2JpaMappingGenerator =
     new Java2JpaMappingGenerator();
java2JpaMappingGenerator.setRenderJpaMappingForClassStrategy(
     new RenderJpaMappingForClassStrategyDefaultImpl());
JpaMappingRendererDefaultImpl jpaMappingRenderer =
     new JpaMappingRendererDefaultImpl("target/META-INF/orm.xml");
java2JpaMappingGenerator.setJpaMappingRenderer(jpaMappingRenderer);
java2JpaMappingGenerator.generateJpaMappingsForPackages("com.test.model.simple");
jpaMappingRenderer.createMappedFiles();
</pre>
<p>This will generate the following orm.xml in the target/META-INF folder:</p>
<pre class="is_code">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;entity-mappings version="2.0"
  xmlns="http://java.sun.com/xml/ns/persistence/orm"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd"&gt;
  &lt;persistence-unit-metadata&gt;
    &lt;xml-mapping-metadata-complete/&gt;
    &lt;persistence-unit-defaults&gt;
      &lt;access&gt;PROPERTY&lt;/access&gt;
    &lt;/persistence-unit-defaults&gt;
  &lt;/persistence-unit-metadata&gt;
  &lt;entity class="com.test.model.simple.Course"&gt;
    &lt;table name="COURSE"/&gt;
    &lt;attributes&gt;
      &lt;id name="id"&gt;
        &lt;generated-value strategy="AUTO"/&gt;
      &lt;/id&gt;
      &lt;one-to-many mapped-by="course" name="students"/&gt;
    &lt;/attributes&gt;
  &lt;/entity&gt;
  &lt;entity class="com.test.model.simple.Student"&gt;
    &lt;table name="STUDENT"/&gt;
    &lt;attributes&gt;
      &lt;id name="studentId"&gt;
        &lt;generated-value strategy="AUTO"/&gt;
      &lt;/id&gt;
      &lt;many-to-one fetch="LAZY" name="course"&gt;
        &lt;join-column name="COURSE_ID"/&gt;
      &lt;/many-to-one&gt;
    &lt;/attributes&gt;
  &lt;/entity&gt;
&lt;/entity-mappings&gt;
</pre>
<div class="is_note">
Note: You can test the generated orm.xml with the JpaMappingTesterOnHsqlImpl Tester implementation. This tester creates the necessary tables based on the orm.xml for an in-memory HSQL database. If it fails, your generated mapping is not valid.<br />
In order to run a JpaMappingTesterOnHsqlImpl test, you will need to have a valid persistence.xml on your classpath(pointing to the generated orm.xml on the classpath &#8211; by default META-INF/orm.xml &#8211; to test).</p>
<pre class="is_code">
JpaMappingTester jpaMappingTester=new JpaMappingTesterOnHsqlImpl("TESTDB");
jpaMappingTester.test();
</pre>
<p>For a working example of using this Tester, check the unit test JpaMappingTesterOnHsqlImplTest in the source code.
</p></div>
<h1 style="padding-top: 10px;">Implementing your own RenderJpaMappingForClassStrategy</h1>
<p>For some models, RenderJpaMappingForClassStrategyDefaultImpl will work out of the box.<br />
However, for most models a different implementation will be necessary.</p>
<p>The following table lists the assumptions this default implementation makes and mentions some override scenario&#8217;s.</p>
<table style="border: 1px solid; vertical-align:top; padding: 0px; margin: 0px; border-collapse:collapse;">
<tr>
<th>Method</th>
<th>Default implementation</th>
<tr>
<tr>
<td style="border: 1px solid; vertical-align:top; padding: 2px;"><span style="font-weight: bold; color: #222222;">public boolean classNeedsMapping(Class clazz)</span><br />
		<i>Returns whether a class needs a jpa mapping.</i></td>
<td style="border: 1px solid; vertical-align:top; padding: 2px;">Class needs mapping if clazz is a top level class, not an interface and not an enum.<br />
		<b>Typical override scenario</b>: In some models, more classes need to be excluded. The default implementation assumes all the classes in the packages to map need jpa mappings.</td>
</tr>
<tr>
<td style="border: 1px solid; vertical-align:top; padding: 2px;"><span style="font-weight: bold; color: #222222;">public ClassRenderType getRenderTypeFor(Class clazz)</span><br />
		<i>Returns how a class should be mapped: MAPPEDSUPERCLASS, ENTITY or EMBEDDABLE.</i></td>
<td style="border: 1px solid; vertical-align:top; padding: 2px;">Abstract classes are mapped as MAPPEDSUPERCLASS. Classes for which the getIdFieldForClass method returns a value are mapped as ENTITY. Other classes are mapped as EMBEDDABLE.<br />
		<b>Typical override scenario</b>: If you want to map the subclasses of an abstract class to one table, you want this method to return ENTITY for the abstract superclass.</td>
</tr>
<tr>
<td style="border: 1px solid; vertical-align:top; padding: 2px;"><span style="font-weight: bold; color: #222222;">public InheritanceMappingType getInheritanceMappingTypeForClass(Class clazz, Collection&lt;Class&gt; allClassesToMap)</span><br />
		<i>Returns how the inheritance of the class should be mapped.</i></td>
<td style="border: 1px solid; vertical-align:top; padding: 2px;">Maps ENTITY classes that are part of an inheritance hierarchy to a single table.<br />
		<b>Typical override scenario</b>: If you want to use another inheritance mapping type, you will need to override the default implementation. However, in order to do so, the code of the tool itself will need to be adapted too.</td>
</tr>
<tr>
<td style="border: 1px solid; vertical-align:top; padding: 2px;"><span style="font-weight: bold; color: #222222;">public CollectionRenderType getCollectionRenderTypeForField(Field field)</span><br />
		<i>Returns how a collection field should be mapped.</i></td>
<td style="border: 1px solid; vertical-align:top; padding: 2px;">Returns null if ParameterizedType of Collection(=&#8221;other class&#8221;) is not known. Returns ONETOMANY if field of type &#8220;class being rendered&#8221; is present on &#8220;other class&#8221;. Returns SIMPLE if field of type &#8220;class being rendered&#8221; is not present on &#8220;other class&#8221; and other class is either a simple class or an enum. Returns MANYTOMANY if field of type &#8220;class being rendered&#8221; is not present on &#8220;other class&#8221; and other class is not a simple class and not an enum.<br />
		<b>Typical override scenario</b>: Sometimes you want to add a MANYTOMANY mapping instead of a ONETOMANY mapping, even if field of type &#8220;class being rendered&#8221; is present on &#8220;other class&#8221;.</td>
</tr>
<tr>
<td style="border: 1px solid; vertical-align:top; padding: 2px;"><span style="font-weight: bold; color: #222222;">public Field getIdFieldForClass(Class clazz)</span><br />
		<i>Returns the field that represents the id for the given class.</i></td>
<td style="border: 1px solid; vertical-align:top; padding: 2px;">If clazz has a field with name &#8220;id&#8221; return that field. Otherwise, if class has field with name &#8220;&lt;simpleClassName&gt;+Id&#8221; return that field.<br />
		<b>Typical override scenario</b>: If the field that corresponds with the database id does not match the &#8220;id&#8221; or &#8220;&lt;simpleClassName&gt;+Id&#8221; naming, you will need to override this method.</td>
</tr>
<tr>
<td style="border: 1px solid; vertical-align:top; padding: 2px;"><span style="font-weight: bold; color: #222222;">public boolean fieldNeedsManyToOneMapping(Field field)</span><br />
		<i>Returns whether a certain field requires a many-to-one mapping.</i></td>
<td style="border: 1px solid; vertical-align:top; padding: 2px;">Field needs mapping if type of field is a top level class, not a simple class, not a standard class, not an array, enum, and field does not have a transient or static modifier.<br />
		<b>Typical override scenario</b>: Sometimes, you will need to exclude more fields, such as log instance variables that do not need to be persisted.</td>
</tr>
</table>
<h1>Limitations of the tool</h1>
<p>The xml mappings generated by the current implementation are far from complete.<br />
Column level details are almost never specified in the generated mappings, only one inheritance mapping strategy is considered and collection cascades need to be added manually.<br />
The tool only creates an initial mapping for each class, avoiding most of the repetitive work involved. </p>
<h1>Stack Overflow</h1>
<p>A while ago <a href="http://stackoverflow.com/questions/15645208/auto-generate-jpa-xml-mappings-from-clean-java-classes-pojos-using-library-too">I asked on Stackoverflow whether a java2jpa tool already existed</a>.<br />
I answered my own answer now by pointing people to my own tool.<br />
If the tool is of use to you, upvotes on that answer are appreciated.<br />
Would be a nice community reward to get some reputation there out of contributing this.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.integratingstuff.com/2013/04/15/java2jpa-automatically-create-jpa-mappings-for-a-java-domain-model/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Starting with OSGI with Maven and Spring, and understanding OSGI dependency problems</title>
		<link>http://www.integratingstuff.com/2012/07/29/starting-with-osgi-with-maven-and-spring-and-understanding-osgi-dependency-problems/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=starting-with-osgi-with-maven-and-spring-and-understanding-osgi-dependency-problems</link>
		<comments>http://www.integratingstuff.com/2012/07/29/starting-with-osgi-with-maven-and-spring-and-understanding-osgi-dependency-problems/#comments</comments>
		<pubDate>Sun, 29 Jul 2012 15:59:52 +0000</pubDate>
		<dc:creator>Steffen Luypaert</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[OSGI]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://www.integratingstuff.com/?p=682</guid>
		<description><![CDATA[In this article, we first cover the Open Services Gateway Initiative(OSGI). Then we setup an OSGI project with Maven. We make sure Maven adds the correct manifest when building a bundle and we automatize testing our bundles inside an OSGI environment. After that we look into understanding OSGI dependency problems.]]></description>
			<content:encoded><![CDATA[<p>In this article, we first cover the Open Services Gateway Initiative(OSGI). Then we setup an OSGI project with Maven. We make sure Maven adds the correct manifest when building a bundle and we automatize testing our bundles inside an OSGI environment. After that we look into understanding OSGI dependency problems.</p>
<h1>OSGI</h1>
<p>The <a href="http://www.osgi.org">Open Services Gateway Initiative (OSGI)</a> makes it possible to break your application into multiple modules which can be independently deployed from each other, making it easier to manage cross-dependencies.<br />
The different modules (coming in the form of bundles/jars for deployment) can be remotely installed, started, stopped, updated, and uninstalled without requiring a reboot.</p>
<h3>OSGI Bundles</h3>
<p>Each bundle is a tightly-coupled, dynamically loadable collection of classes, jars and configuration files that explicitly declares its external dependencies (if any).<br />
Each bundle contains a detailed manifest MANIFEST.MF file, which includes different OSGI tags, and which is what  physically makes an OSGI bundle different from a non-OSGI Java jar.</p>
<p>An example of such a manifest file:</p>
<pre class="is_code">
Bundle-Name: Integrating Stuff OSGI test
Bundle-SymbolicName: com.integratingstuff.osgi
Bundle-Description: A Test OSGI bundle
Bundle-ManifestVersion: 2
Bundle-Version: 1.0.0
Bundle-Activator: com.integratingstuff.osgi.BundleActivator
Export-Package: com.integratingstuff.osgi;version="1.0.0"
Import-Package: org.osgi.framework;version="1.3.0"
</pre>
<p>Hence, building an OSGI jar instead of a regular jar comes down to setting the values in this manifest file correctly.</p>
<p>The first 5 tags in the example are obvious.</p>
<p>The 3 last ones are the more interesting ones:<br />
<strong>Bundle-Activator</strong>: Indicates the class name to be invoked once a bundle is activated.<br />
<strong>Export-Package</strong>: Expresses what Java packages contained in a bundle will be made available to the outside world.<br />
<strong>Import-Package</strong>: Indicates what Java packages will be required from the outside world, in order to fulfill the dependencies needed in a bundle.</p>
<h3>Activator</h3>
<p>The Bundle-Activator <a href="http://www.osgi.org/javadoc/r4v43/core/org/osgi/framework/BundleActivator.html">BundleActivator class</a>, declared in the manifest file, will be invoked once a bundle is activated. A typical OSGI jar, which contains services that should be registered with the OSGI container, contains such a Bundle-Activator declaration.<br />
However, the declaration of a Bundle-Activator is optional. Some jars will only export certain packages and will not need a bundle activator/not register any services. The OSGI jar for the Spring framework, for example, does not require a Bundle Activator. All it does is exporting packages for other OSGI bundles to use.</p>
<p>An example of a typical BundleActivator:</p>
<pre class="is_code">
public class Activator implements BundleActivator {

        public void start(BundleContext context) throws Exception {
                System.out.println("Starting: Integrating OSGI stuff");
                context.registerService(AccountService.class.getName(),
			new AccountServiceImpl(), null);
        }

        public void stop(BundleContext context) throws Exception {
                System.out.println("Stopping with integrating OSGI stuff");
                ServiceReference serviceReference = context.
			getServiceReference(AccountService.class.getName());
		if (serviceReference != null){
			context.ungetService(serviceReference);
		};
        }
}
</pre>
<p>For brevity, we do not include the AccountService class here. To compile this, you will also need the osgi-core lib on your classpath. If you want to experiment with the code, please download the Maven project made available in the last section of this article.</p>
<h3>OSGI Lifecycle</h3>
<p>The OSGI life cycle layer introduces dynamics that are normally not part of an application. </p>
<p>Every bundle within the OSGI container can be in one of the following states thanks to this mechanism:</p>
<p><strong>Installed</strong>: The bundle has been successfully installed.<br />
<strong>Resolved</strong>: All Java classes that the bundle needs are available. This state indicates that the bundle is either ready to be started or has stopped.<br />
<strong>Starting</strong>: The bundle is being started, the BundleActivator.start method will be called, and this method has not yet returned. When the bundle has an activation policy, the bundle will remain in the Starting state until the bundle is activated according to its activation policy..<br />
<strong>Active</strong>: The bundle has been successfully activated and is running; its Bundle Activator start method has been called and returned.<br />
<strong>Stopping</strong>: The bundle is being stopped. The BundleActivator.stop method has been called but the stop method has not yet returned.<br />
<strong>Uninstalled</strong>: The bundle has been uninstalled. It cannot move into another state.</p>
<h3>OSGI containers</h3>
<p>There are 3 popular OSGI container implementations: <a href="http://www.knopflerfish.org/">Knopflerfish</a>, <a href="http://www.eclipse.org/equinox/">Equinox</a>, and <a href="http://felix.apache.org">Apache Felix</a>. <a href="http://concierge.sourceforge.net/">Concierge</a> seems to be receiving a lot of adaptation on mobile and embedded devices too, due to its limited file footprint of about 80 kBytes.</p>
<h1>Adding the correct manifest to your bundle with Maven</h1>
<p>To make sure Maven adds the correct manifest to our bundle, we use the <a href="http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html">org.apache.felix maven-bundle-plugin</a>. This plugin generates the correct manifest for us, based on the configuration we pass, configured through Maven properties.<br />
We also use the maven-dependency-plugin to be able to embed libraries and we configure the maven-jar-plugin to use the generated manifest file.</p>
<p>This is how our pom.xml looks like:</p>
<pre class="is_code">
&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
  &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
  &lt;groupId&gt;com.integratingstuff&lt;/groupId&gt;
  &lt;artifactId&gt;com.integratingstuff.osgi&lt;/artifactId&gt;
  &lt;version&gt;1.0.0&lt;/version&gt;
  &lt;name&gt;com.integratingstuff.osgi&lt;/name&gt; 

  &lt;build&gt;
    &lt;plugins&gt;
      &lt;!-- this is needed to enable reference in the Manifest file to Embedded libraries --&gt;
      &lt;plugin&gt;
        &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
        &lt;artifactId&gt;maven-dependency-plugin&lt;/artifactId&gt;
        &lt;executions&gt;
          &lt;execution&gt;
            &lt;id&gt;copy-dependencies&lt;/id&gt;
            &lt;phase&gt;compile&lt;/phase&gt;
            &lt;goals&gt;
              &lt;goal&gt;copy-dependencies&lt;/goal&gt;
            &lt;/goals&gt;
          &lt;/execution&gt;
        &lt;/executions&gt;
      &lt;/plugin&gt;

      &lt;plugin&gt;
        &lt;artifactId&gt;maven-jar-plugin&lt;/artifactId&gt;
        &lt;version&gt;2.3.2&lt;/version&gt;
        &lt;configuration&gt;
          &lt;archive&gt;
            &lt;manifestFile&gt;${manifestFile}&lt;/manifestFile&gt;
          &lt;/archive&gt;
        &lt;/configuration&gt;
      &lt;/plugin&gt;
      &lt;plugin&gt;
        &lt;groupId&gt;org.apache.felix&lt;/groupId&gt;
        &lt;artifactId&gt;maven-bundle-plugin&lt;/artifactId&gt;
        &lt;version&gt;2.3.6&lt;/version&gt;
        &lt;extensions&gt;true&lt;/extensions&gt;
        &lt;configuration&gt;
          &lt;manifestLocation&gt;${manifestFolder}&lt;/manifestLocation&gt;
          &lt;excludeDependencies&gt;${maven.bundleplugin.exclude.dependencies}&lt;/excludeDependencies&gt;
          &lt;instructions&gt;
            &lt;Bundle-SymbolicName&gt;${project.build.bundle.symbolicname}&lt;/Bundle-SymbolicName&gt;
            &lt;Bundle-Name&gt;${project.build.bundle.name}&lt;/Bundle-Name&gt;
            &lt;Bundle-Version&gt;${project.build.bundle.version}&lt;/Bundle-Version&gt;
            &lt;Bundle-Activator&gt;${project.build.bundle.activator}&lt;/Bundle-Activator&gt;
            &lt;Import-Package&gt;${project.build.import.package}&lt;/Import-Package&gt;
            &lt;Export-Package&gt;${project.build.export.package}&lt;/Export-Package&gt;
            &lt;Private-Package&gt;${project.build.private.package}&lt;/Private-Package&gt;
            &lt;Web-ContextPath&gt;${project.build.web.contextpath}&lt;/Web-ContextPath&gt;
            &lt;Webapp-Context&gt;${project.build.web.contextpath}&lt;/Webapp-Context&gt;
            &lt;Bundle-ClassPath&gt;${project.build.bundle.classpath}&lt;/Bundle-ClassPath&gt;
            &lt;Embed-Dependency&gt;${project.build.embed.dependency}&lt;/Embed-Dependency&gt;
            &lt;Embed-Directory&gt;${project.build.embed.directory}&lt;/Embed-Directory&gt;
            &lt;Embed-Transitive&gt;${project.build.embed.transitive}&lt;/Embed-Transitive&gt;
          &lt;/instructions&gt;
          &lt;supportedProjectTypes&gt;
            &lt;supportedProjectType&gt;jar&lt;/supportedProjectType&gt;
            &lt;supportedProjectType&gt;bundle&lt;/supportedProjectType&gt;
            &lt;supportedProjectType&gt;war&lt;/supportedProjectType&gt;
          &lt;/supportedProjectTypes&gt;
        &lt;/configuration&gt;
        &lt;executions&gt;
          &lt;execution&gt;
            &lt;id&gt;bundle-manifest&lt;/id&gt;
            &lt;phase&gt;process-classes&lt;/phase&gt;
            &lt;goals&gt;
              &lt;goal&gt;manifest&lt;/goal&gt;
            &lt;/goals&gt;
          &lt;/execution&gt;
        &lt;/executions&gt;

      &lt;/plugin&gt;
    &lt;/plugins&gt;
  &lt;/build&gt;

  &lt;properties&gt;
    &lt;project.build.bundle.symbolicname&gt;${project.artifactId}&lt;/project.build.bundle.symbolicname&gt;
    &lt;project.build.bundle.name&gt;${project.name}&lt;/project.build.bundle.name&gt;
    &lt;project.build.bundle.version&gt;${project.version}&lt;/project.build.bundle.version&gt;
    &lt;project.build.bundle.activator&gt;&lt;/project.build.bundle.activator&gt;
    &lt;project.build.import.package&gt;*&lt;/project.build.import.package&gt;
    &lt;project.build.export.package&gt;*&lt;/project.build.export.package&gt;
    &lt;project.build.private.package&gt;&lt;/project.build.private.package&gt;
    &lt;project.build.bundle.classpath&gt;&lt;/project.build.bundle.classpath&gt;
    &lt;project.build.web.contextpath&gt;&lt;/project.build.web.contextpath&gt;
    &lt;project.build.embed.dependency&gt;&lt;/project.build.embed.dependency&gt;
    &lt;project.build.embed.directory&gt;&lt;/project.build.embed.directory&gt;
    &lt;project.build.embed.transitive&gt;&lt;/project.build.embed.transitive&gt;
    &lt;manifestFolder&gt;src/main/resources/META-INF&lt;/manifestFolder&gt;
    &lt;manifestFile&gt;${manifestFolder}/MANIFEST.MF&lt;/manifestFile&gt;
  &lt;/properties&gt;

&lt;/project&gt;
</pre>
<h1>Testing OSGI bundles with Spring</h1>
<p>When building OSGI bundles, it is probably a good idea to check whether the built bundles are valid. We are going to check this by writing unit tests that extend from <a href="http://static.springsource.org/osgi/docs/1.2.1/api/org/springframework/osgi/test/AbstractConfigurableBundleCreatorTests.html">AbstractConfigurableBundleCreatorTests</a>, from the spring-osgi-mock jar. This test will start an OSGI container and run the test in it. Tests like these can catch OSGI dependency problems automatically, requiring no manual deploy, allowing easy OSGI integration testing.</p>
<p>To start, add the following dependencies section to the Maven pom.xml:</p>
<pre class="is_code">
&lt;dependencies&gt;
  &lt;!-- test dependencies --&gt;
  &lt;dependency&gt;
    &lt;groupId&gt;org.springframework.osgi&lt;/groupId&gt;
    &lt;artifactId&gt;spring-osgi-core&lt;/artifactId&gt;
    &lt;version&gt;1.2.1&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
  &lt;/dependency&gt;
  &lt;dependency&gt;
    &lt;groupId&gt;org.springframework.osgi&lt;/groupId&gt;
    &lt;artifactId&gt;spring-osgi-mock&lt;/artifactId&gt;
    &lt;version&gt;1.2.1&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
  &lt;/dependency&gt;
  &lt;dependency&gt;
    &lt;groupId&gt;org.springframework.osgi&lt;/groupId&gt;
    &lt;artifactId&gt;spring-osgi-test&lt;/artifactId&gt;
    &lt;version&gt;1.2.1&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
  &lt;/dependency&gt;
  &lt;dependency&gt;
    &lt;groupId&gt;org.springframework.osgi&lt;/groupId&gt;
    &lt;artifactId&gt;spring-osgi-annotation&lt;/artifactId&gt;
    &lt;version&gt;1.2.1&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
  &lt;/dependency&gt;
  &lt;dependency&gt;
    &lt;groupId&gt;org.springframework.osgi&lt;/groupId&gt;
    &lt;artifactId&gt;spring-osgi-extender&lt;/artifactId&gt;
    &lt;version&gt;1.2.1&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
  &lt;/dependency&gt;

  &lt;dependency&gt;
    &lt;groupId&gt;org.apache.felix&lt;/groupId&gt;
    &lt;artifactId&gt;org.osgi.core&lt;/artifactId&gt;
    &lt;version&gt;1.4.0&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
  &lt;/dependency&gt;
  &lt;dependency&gt;
    &lt;groupId&gt;org.apache.felix&lt;/groupId&gt;
    &lt;artifactId&gt;org.apache.felix.framework&lt;/artifactId&gt;
    &lt;version&gt;1.7.0-private&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
  &lt;/dependency&gt;
  &lt;dependency&gt;
    &lt;groupId&gt;org.apache.felix&lt;/groupId&gt;
    &lt;artifactId&gt;org.apache.felix.main&lt;/artifactId&gt;
    &lt;version&gt;1.7.0-private&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
  &lt;/dependency&gt;

  &lt;!-- from http://dev.anyframejava.org/maven/repo/org/springframework/osgi/log4j.osgi/1.2.15-SNAPSHOT/ --&gt;
  &lt;dependency&gt;
    &lt;groupId&gt;org.springframework.osgi&lt;/groupId&gt;
    &lt;artifactId&gt;log4j.osgi&lt;/artifactId&gt;
    &lt;version&gt;1.2.15-SNAPSHOT&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
  &lt;/dependency&gt;
&lt;/dependencies&gt;
</pre>
<p>This will add the <a href="http://www.springsource.org/osgi/">spring osgi</a> dependencies we need. </p>
<p>This will also add all the dependencies needed to run the Felix OSGI container, which will be the OSGI container we will run our tests in.</p>
<p>Note: You might need to download and install the log4j.osgi manually from <a href="http://dev.anyframejava.org/maven/repo/org/springframework/osgi/log4j.osgi/1.2.15-SNAPSHOT">http://dev.anyframejava.org/maven/repo/org/springframework/osgi/log4j.osgi/1.2.15-SNAPSHOT</a> into your own nexus or local maven repo.</p>
<p>Then add the following test:</p>
<pre class="is_code">
public class LoadOSGITestCase extends AbstractConfigurableBundleCreatorTests{

	@Override
	protected String[] getTestBundlesNames() {
		return new String[] { "com.integratingstuff, com.integratingstuff.osgi, 1.0.0" };
	}

	public void testOSGIPlatformStarts() throws Exception {
		System.out.println(bundleContext.getProperty(Constants.FRAMEWORK_VENDOR));
		System.out.println(bundleContext.getProperty(Constants.FRAMEWORK_VERSION));
		System.out.println(bundleContext.getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT));
	}

	public void testOSGIEnvironment() throws Exception {
		Bundle[] bundles = bundleContext.getBundles();
		for (int i = 0; i &lt; bundles.length; i++) {
			System.out.print(OsgiStringUtils.nullSafeName(bundles[i]));
			System.out.print(", ");
		}
	}

	public void testRetrieveService() throws Exception {
		Properties props = new Properties();
		props.put("Language", "English");

		ServiceTracker accountServiceTracker = new ServiceTracker(bundleContext, AccountService.class.getName(), null);
		accountServiceTracker.open();
		AccountService accountService = (AccountService) accountServiceTracker.getService();
		accountService.createAccount(1000l);
	}

	@Override
	protected String getPlatformName() {
		return Platforms.FELIX;
	}

}
</pre>
<p>And run it.</p>
<p>These tests will run within the Felix OSGI container. The two first tests just write out some info about the OSGI environment itself. The last test fetches a reference to this service and then calls a method on it.</p>
<h1>Troubleshooting OSGI dependency problems</h1>
<p>When starting with OSGI, you need to get used to not having a global classpath, but instead, take into account which packages a bundle exports or imports.</p>
<p>You might run into problems because of this. In what follows, we cover some common import/export package mistakes. Different OSGI containers can have different implementations, so the error messages you see because of these mistakes might differ a bit. One OSGI container might fail to resolve a bundle because of a conflict, while another one might just load one of two conflicting bundles and report a ClassNotFoundException when a class residing in a discarded or unknown bundle is used. In certain containers, it is possible to get away with making one of the mistakes covered here, in certain circumstances. Still, they are errors against the specification and should always be avoided.</p>
<p>If you want to experiment with these errors to better understand them, please download <a href="http://www.integratingstuff.com/wp-content/uploads/2012/07/OSGITestProject.zip">this OSGI test project</a>. It is in a correct starting state, but in what follows, we will indicate how to produce every covered error using this project.<br />
Any of these errors will cause the unit test in the com.integratingstuff.osgi.test module to fail.</p>
<h3>Failing to export a package needed by another bundle</h3>
<p>This error can be produced by changing the project.build.export.package Maven property in the pom.xml of the com.integratingstuff.osgi.services1 module to “com.test.model” instead of “*”. Then com.test.service of the com.integratingstuff.osgi.services1 module will not be exported then(not declared in the Export-Package section of the manifest), and the AccountService class will not be available to other modules that need it, such as the com.integratingstuff.osgi.services2 module.</p>
<h3>Failing to import a required package</h3>
<p>This error can be produced by changing the project.build.import.package Maven property in the pom.xml of the com.integratingstuff.osgi.services2 module to “com.test.model” instead of “*”. Then com.test.service of the com.integratingstuff.osgi.services1 module will not be imported then(not declared in the Import-Package section of the manifest), and the AccountService class will be unknown to the com.integratingstuff.osgi.services2 module.</p>
<h3>Exporting conflicting packages</h3>
<p>This error can be produced by renaming the com.test.person.service package in the com.integratingstuff.osgi.services2 module to com.test.service, so it conflicts with the com.test.service package of the com.integratingstuff.osgi.services1 module.</p>
<p>Depending on the container, bundles importing the conflicting package will not resolve(“package uses conflict” errors) or only one of the two conflicting packages will be known by the container, resulting in ClassNotFoundExceptions.</p>
<p>In an OSGI environment, two bundles should not export a package with the same name.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.integratingstuff.com/2012/07/29/starting-with-osgi-with-maven-and-spring-and-understanding-osgi-dependency-problems/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Setting up a MongoDb Replica Set with an Arbiter on Amazon EC2 with Amazon Cloudformation</title>
		<link>http://www.integratingstuff.com/2012/06/18/setting-up-a-mongodb-replica-set-with-an-arbiter-on-amazon-ec2-with-amazon-cloudformation/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=setting-up-a-mongodb-replica-set-with-an-arbiter-on-amazon-ec2-with-amazon-cloudformation</link>
		<comments>http://www.integratingstuff.com/2012/06/18/setting-up-a-mongodb-replica-set-with-an-arbiter-on-amazon-ec2-with-amazon-cloudformation/#comments</comments>
		<pubDate>Mon, 18 Jun 2012 07:02:11 +0000</pubDate>
		<dc:creator>Steffen Luypaert</dc:creator>
				<category><![CDATA[Amazon AWS]]></category>
		<category><![CDATA[MongoDb]]></category>
		<category><![CDATA[NoSql]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[CloudFormation]]></category>
		<category><![CDATA[EC2]]></category>
		<category><![CDATA[MMS]]></category>

		<guid isPermaLink="false">http://www.integratingstuff.com/?p=649</guid>
		<description><![CDATA[In this article, we will set up a MongoDB ReplicaSet with an Arbiter on EC2 using Cloudformation templates. First, MongoDB, Amazon EC2 and Amazon CloudFormation are briefly introduced, after which we provide the CloudFormation templates to set up the MongoDb replica set with the Arbiter.
Finally, we provide a CloudFormation template to set up the Mongo Monitoring Service on a seperate EC2 instance.]]></description>
			<content:encoded><![CDATA[<p>In this article, we will set up a MongoDB ReplicaSet with an Arbiter on EC2 using Cloudformation templates. First, MongoDB, Amazon EC2 and Amazon CloudFormation are briefly introduced, after which we provide the CloudFormation templates to set up the MongoDb replica set with the Arbiter.<br />
Finally, we provide a CloudFormation template to set up the Mongo Monitoring Service on a separate EC2 instance.</p>
<p>It is recommended that readers already have some experience with MongoDb and Amazon EC2.</p>
<h1>Introduction</h1>
<h2>What is MongoDB?</h2>
<p><a href="http://www.mongodb.org/">MongoDB</a> is an open source document-oriented NoSQL database.</p>
<p>Instead of storing data in tables as is done in a &#8220;classical&#8221; relational database, MongoDB stores structured data as JSON-like documents with dynamic schemas(&#8220;BSON&#8221;).</p>
<p>Although earlier versions of MongoDB were criticized, &#8220;<a href="http://www.mongodb-is-web-scale.com/">MongoDB is Web scale</a>&#8220;, these issues were resolved(for example, <a href="http://www.mongodb.org/display/DOCS/Journaling">journaling is enabled by default now</a>). MongoDb is now mature and production ready, and it is used extensively by MTV, Craigslist and Foursquare among others.</p>
<p>Whether you should use it or not depends. <a href="http://refcardz.dzone.com/refcardz/getting-started-nosql-and-data">This Dzone Reference Card on Getting Started with NoSql</a> might help. It advises to base the choice around Brewer&#8217;s CAP Theorem: &#8220;It&#8217;s impossible for a distributed computer system to simultaneously provide Consistency, Availability and Partition Tolerance&#8221;. Decide which 2 of these you need most, and you know what type of database you need.</p>
<p>MongoDB offers a lot of the features RDBMS databases offer, such as adding indices to and querying on all fields. Some NoSql databases/services, such as <a href="http://aws.amazon.com/dynamodb/">Amazon DynamoDB</a> lack this, which makes their use rather limited. </p>
<p>However, MongoDB does not enforce consistency. You can put a reference(DBRef) in a record in collection1(a MongoDB &#8220;collection&#8221; is the equivalent of a RDBMS table) to a record in collection2 and then delete the record in collection2. No error would be thrown. The reference would still be there, but when someone would try to resolve it, no record in collection2 would be found.</p>
<p>What MongoDB offers in return however, is <a href="http://en.wikipedia.org/wiki/Replication_(computing)">easy replication</a> and <a href="http://en.wikipedia.org/wiki/Sharding">sharding</a>, which makes it excel at Availability and Partition Tolerance. Unlike RDBMS databases, which are usually <a href="http://en.wikipedia.org/wiki/Scalability#Scale_horizontally_vs._vertically">scaled vertically</a>(&#8220;making the machine bigger&#8221;), MongoDB can be easily <a href="http://en.wikipedia.org/wiki/Scalability#Scale_horizontally_vs._vertically">scaled horizontally</a>( &#8220;adding more machines&#8221;).</p>
<div class="is_note">
Note: It is not true that RDBMS databases cannot be scaled horizontally. However, this is usually done by adding an extra layer between the application layer and the database layer, or by handling this in the application layer itself(for example, by adding code that is able to determine in what database a record resides). No need to say the required referential integrity usually makes this quite difficult, and in some cases, referential integrity is loosened a bit to make horizontal scalability for the RDBMS database possible.</p>
<p>Similarly, MongoDB databases usually never end up in an inconsistent state, since data is checked in the application layer before it is put in or removed from the database. Consistency is just not enforced by the database itself.</p>
<p>As a rule of thumb, if you need consistency more than horizontal scalability, go RDBMS, if you need horizontal scalability more than consistency, go NoSql.
</p></div>
<h2 style="padding-top: 10px;">What is Amazon EC2?</h2>
<p>The <a href="http://aws.amazon.com/ec2/">Amazon Elastic Compute Cloud</a>(Amazon EC2) is a central part of Amazon&#8217;s cloud computing platform <a href="http://aws.amazon.com">Amazon Web Services</a>(AWS).<br />
Users can rent virtual computers on EC2 to which they get full root access.<br />
They pay by the hour for active servers, hence the term &#8220;elastic&#8221;. EC2 makes scalable deployment of applications easy by providing a web service through which users can boot instances by providing a machine image(for example, a Linux Image on which Apache/Php/Wordpress/Mysql or Java/Tomcat is already installed).</p>
<p>Although using <a href="http://www.mysqlperformanceblog.com/2011/02/21/death-match-ebs-versus-ssd-price-performance-and-qos/">Amazon EC2 is not necessarily less expensive than buying your own hardware</a>, it is a good choice for most startups, since instances can be easily added or removed, or replaced by larger or smaller ones. You can scale your costs with your load, and thus, you are protected against overinvestment and you are prepared for scaling up in a matter of minutes in case you get a traffic peak.</p>
<p>Many startups, such as Foursquare and BitBucket, run entirely on Amazon EC2/AWS.</p>
<h2>What is Amazon CloudFormation?</h2>
<p>There are 3 interfaces through which EC2 instances/AWS Resources can be set up. The first one is the web interface, which provides an intuitive graphical interface. The second one consists of the <a href="http://aws.amazon.com/developertools/351">EC2 Command Line Tools</a>, which make it possible to launch and manage instances through scripting and which are used by third party AWS tools such as the AWS/EC2 Plugin for Eclipse.</p>
<p>The third one is <a href="http://aws.amazon.com/cloudformation/">CloudFormation</a>. With Amazon CloudFormation, you describe AWS resources in a template. You then instruct Amazon CloudFormation to read this template and initialize the resources associated with it.</p>
<p>If you&#8217;ve never used CloudFormation before, you should go through its <a href="http://docs.amazonwebservices.com/AWSCloudFormation/latest/UserGuide/GettingStarted.html">Getting Started Guide</a>. We will only discuss the basic layout of a Cloudformation template file here briefly. There are 4 sections that appear in almost every template. We will use snippets of a Tomcat 7 template as examples.</p>
<h4>Parameters</h4>
<p>When a template is loaded, CloudFormation prompts the user to enter a value for every parameter that is defined in the Parameters section.</p>
<p>An example Parameters section:</p>
<pre class="is_code">
"Parameters" : {
        "KeyName" : {
            "Description" : "Name of an existing EC2 KeyPair to enable SSH access",
            "Type" : "String"
        },

        "InstanceType" : {
            "Type" : "String",
            "Default" : "m1.large",
            "AllowedValues" : [ "t1.micro", "m1.small", "m1.medium", "m1.large", "m1.xlarge", "m2.xlarge", "m2.2xlarge", "m2.4xlarge", "c1.xlarge", "cc1.4xlarge" ],
            "Description" : "EC2 instance type (e.g. t1.micro, m1.small, m1.medium, m1.large, m1.xlarge, m2.xlarge)"
        },

        "SecurityGroupName" : {
            "Description" : "Security group name for the instance",
            "Type" : "String"
        }
}
</pre>
<p>With the above example, the user will be prompted for the name of a ssh keypair, the type of the EC2 instance that will be created by the template and the name of the security group to which this instance will belong.</p>
<h4>Mappings</h4>
<p>In the Mappings section, mappings of certain values to other values are described.</p>
<p>An example Mappings section: </p>
<pre class="is_code">
"Mappings" : {
        "RegionImageZone" : {
            "us-east-1"      : { "64" : "ami-e565ba8c"},
            "us-west-2"      : { "64" : "ami-3ac64a0a"},
            "us-west-1"      : { "64" : "ami-e78cd4a2"},
            "eu-west-1"      : { "64" : "ami-f9231b8d"},
            "ap-southeast-1" : { "64" : "ami-be3374ec"},
            "ap-northeast-1" : { "64" : "ami-e47acbe5"},
            "sa-east-1"      : { "64" : "ami-a6855bbb"}
        }
}
</pre>
<p>The above mapping could be used in a template to determine the code for the AMI(Amazon Machine Image) to be used for a certain region. The above mappings point to the basic Amazon Linux AMI for different regions. Since the template knows on which region it is executing, providing and using a mapping like this is usually a good idea.</p>
<h4>Resources</h4>
<p>This is the most important section of the template and describes the resources to initialize. EC Instances are typically seen here, but other kinds of AWS Resources can be defined as well, such as security rules and <a href="http://aws.amazon.com/s3/">S3</a>(Amazon Simple Storage Service, often used extensively with EC2 Instances) resources.</p>
<p>In our example, the only resource associated with the template is an EC2 instance on which a Tomcat 7 server will be installed:</p>
<pre class="is_code">
"Resources" : {
        "Tomcat7" : {
            "Type" : "AWS::EC2::Instance",
            "Metadata" : {
                "AWS::CloudFormation::Init" : {
                    "config" : {
                        "packages" : {
                            "yum" : {
                                "apr-devel" : [],
                                "openssl-devel" : [],
                                "gcc" : [],
                                "java-1.6.0-openjdk-devel" : [],
                                "tomcat7": []
                            }
                        }
                    }
                }
            },

            "Properties" : {
                "InstanceType" : { "Ref" : "InstanceType" },
                "ImageId" : { "Fn::FindInMap" : [ "RegionImageZone", { "Ref" : "AWS::Region" }, "64" ] },
                "SecurityGroups" : [ { "Ref" : "SecurityGroupName" } ],
                "KeyName" : { "Ref" : "KeyName" },
                "Tags" : [
          			{"Key" : "Name", "Value" : "Tomcat7" }
        		]}
	}
}
</pre>
<p>Notice how both the Parameters (with &#8220;Ref&#8221;) and the Mappings(with &#8220;Fn::FindInMap&#8221;) section are used to init the instance. </p>
<h4>Outputs</h4>
<p>The Outputs of the template. This could be the public ip of the created instance.</p>
<p>An example outputs section: </p>
<pre class="is_code">
"Outputs" : {
        "InstanceName" : {
            "Value" : { "Fn::GetAtt" : [ "Tomcat7", "PublicDnsName" ] },
            "Description" : "public DNS name of the new Tomcat7"
        }
    }
</pre>
<p>Outputs are visible in the &#8220;Outputs&#8221; tab of the CloudFormation web interface:</p>
<p><a href="http://www.integratingstuff.com/wp-content/uploads/2012/06/cloudformation_template_outputs.png"><img src="http://www.integratingstuff.com/wp-content/uploads/2012/06/cloudformation_template_outputs.png" alt="Amazon CloudFormation Template Outputs" title="Amazon CloudFormation Template Outputs" width="600" height="116" class="aligncenter size-medium wp-image-655" /></a></p>
<h1>The CloudFormation templates for setting up a MongoDb replicaset with an Arbiter</h1>
<h2>What is a MongoDb replicaset?</h2>
<p><a href="http://www.mongodb.org/display/DOCS/Replica+Sets">A MongoDb replicaset</a> is a form of asynchronous master/slave replication, adding automatic failover and automatic recovery of member nodes. It is heavily recommended to never deploy MongoDb to one standalone machine, but always to replicasets, in sets of 3 or a higher uneven number of machines. A normal full replicaset features 3 nodes that store data. In a replicaset with 2 nodes and an arbiter, only the first 2 nodes store data. The master only replicates the data to the one slave. The arbiter is only there in case a new master needs to be elected. It is necessary to prevent MongoDb to go in read-only mode if one of the two other nodes goes down.</p>
<h2>The 10gen templates vs our templates</h2>
<p>10gen, the MongoDB company, already has extensive documentation on <a href="http://www.mongodb.org/display/DOCS/Amazon+EC2">how to setup MongoDB on EC2</a>, including documentation on <a href="http://www.mongodb.org/display/DOCS/Amazon+EC2+Quickstart">how to setup a replicaset on EC2</a>, and even provides <a href="http://www.mongodb.org/display/DOCS/Automating+Deployment+with+CloudFormation">Cloudformation templates to setup a replicaset</a>. </p>
<p>Our templates, which describe a (more budget) MongoDb replicaset consisting of 2 normal nodes and an arbiter as opposed to a replicaset consisting of 3 normal nodes &#8211; are heavily based on these 10gen Cloudformation templates.</p>
<p>We did make some changes to these templates which we consider improvements though:</p>
<ul>
<li>Instead of 4 S3 volumes in RAID 10 per node, our template inits <strong>8 S3 volumes</strong> in RAID 10 per node. This is what the 10gen documentation recommends.</li>
<li>The <strong>nodiratime</strong> directive was added to all mounts in /etc/fstab. This is also what the 10gen documentation recommends.</li>
<li><strong>File descriptor limits were raised</strong> in /etc/security/limits.conf(&#8220;* hard nofile 100000&#8243; and &#8220;* soft nofile 100000&#8243;) Raising file descriptor limits is also recommended by 10gen for production deployments.</li>
</ul>
<p>We also made the following changes. These are not necessarily improvements:</p>
<ul>
<li>Security group definitions are not included in our templates, so you need to create these manually yourself before you can use our templates. Although this requires a bit more EC2 Knowledge, you probably don&#8217;t want to tie these security groups to only this Cloudformation stack. If you run the template again later, you probably want to put the new instances in the same security group again, not create a new one with the same security rules.</li>
<li>Although 10gen recommends to not use anything smaller than a large instance(m1.large) for MongoDB production deployments, large instances are expensive to test on. Therefore, we made it possible to select the Micro(t1.micro) and Small(m1.small) instance types for the normal MongoDb nodes as well.</li>
</ul>
<h2>The CloudFormation templates for a MongoDb replicaset with an Arbiter</h2>
<p><strong>IMPORTANT!</strong> Remember that running these templates on CloudFormation will create AWS resources and Amazon will bill you for AWS resource usage! These templates will create EC2 instances, S3 volumes and some IAM security resources. When t1.micro instances are chosen, it should be possible to test these templates entirely on the Amazon AWS Free Tier, but we do not guarantee this.</p>
<p>The templates:</p>
<ul>
<li><a href="https://s3.amazonaws.com/IntegratingStuff/ReplicaSetWithArbiter.template">ReplicaSetWithArbiter.template</a>: This template will first initialize a slave and an arbiter instance by using the templates below, and then init the master instance.</li>
<li><a href="https://s3.amazonaws.com/IntegratingStuff/MongoDbServer.template">MongoDbServer.template</a>: This template describes the instance that will be configured as the slave of the replicaset. When run seperately, this creates a standalone MongoDb server.</li>
<li><a href="https://s3.amazonaws.com/IntegratingStuff/Arbiter.template">Arbiter.template</a>: This template describes the Arbiter instance.</li>
</ul>
<p>To setup the replicaset, it is enough to provide the first url to CloudFormation. It will call the other two templates itself.</p>
<p>If you are heading towards a production MongoDB deployment, it is probably best to download and host these templates yourself. In that case, you will need to change the TemplateUrl of the Arbiter and the Secondary instance in the ReplicaSetWithArbiter.template file to your own url.</p>
<h2>A CloudFormation template for the Mongo Monitoring Service</h2>
<p>The <a href="http://www.10gen.com/mongodb-monitoring-service">Mongo Monitoring Service</a>(MMS) enables you to proactively monitor your MongoDb cluster. First, you set up an mms agent that has access to your MongoDb nodes. This agent will then fetch metrics from your mongos and send these to 10gen servers, which will show you different graphs about your MongoDb deployment. </p>
<p>First, you will need to sign up for this monitoring service through <a href="http://www.10gen.com/mongodb-monitoring-service">http://www.10gen.com/mongodb-monitoring-service</a>. After signing up, you can retrieve your API key and Secret key, both necessary to setup the agent.</p>
<p>You can then use the following CloudFormation template to set up the mms agent on an EC2 Micro instance:</p>
<p><a href="https://s3.amazonaws.com/IntegratingStuff/MongoMonitoringServer.template">MongoMonitoringServer.template</a></p>
<p>After setting up this Micro instance, you only need to add the hosts(in case of a replicaset, at least one ip to a mongo node; mms will find the other nodes) through the mss web interface, as explained in its documentation.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.integratingstuff.com/2012/06/18/setting-up-a-mongodb-replica-set-with-an-arbiter-on-amazon-ec2-with-amazon-cloudformation/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Hook into Wikipedia using Java and the MediaWiki API</title>
		<link>http://www.integratingstuff.com/2012/04/06/hook-into-wikipedia-using-java-and-the-mediawiki-api/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=hook-into-wikipedia-using-java-and-the-mediawiki-api</link>
		<comments>http://www.integratingstuff.com/2012/04/06/hook-into-wikipedia-using-java-and-the-mediawiki-api/#comments</comments>
		<pubDate>Fri, 06 Apr 2012 12:43:55 +0000</pubDate>
		<dc:creator>Steffen Luypaert</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Wikipedia API]]></category>
		<category><![CDATA[Java Wikipedia API]]></category>
		<category><![CDATA[Webservices]]></category>
		<category><![CDATA[Wikimedia]]></category>

		<guid isPermaLink="false">http://www.integratingstuff.com/?p=624</guid>
		<description><![CDATA[The Mediawiki API makes it possible for web developers to access, search and integrate all Wikipedia content into their applications.
Given that <a href="http://en.wikipedia.org">Wikipedia</a> is the ultimate online encyclopedia, there are dozens of use cases in which this might be useful.

I used to post a lot of articles about using the webservice APIS of third party sites on this blog. This is going to be another post like that.
This post describes how to use the Java Wikipedia API to fetch and format the contents of a Wikipedia article.]]></description>
			<content:encoded><![CDATA[<p>The Mediawiki API makes it possible for web developers to access, search and integrate all Wikipedia content into their applications.<br />
Given that <a href="http://en.wikipedia.org">Wikipedia</a> is the ultimate online encyclopedia, there are dozens of use cases in which this might be useful.</p>
<p>I used to post a lot of articles about using the webservice APIS of third party sites on this blog. This is going to be another post like that.<br />
This post describes how to use the Java Wikipedia API to fetch and format the contents of a Wikipedia article.</p>
<h1>The Wikipedia API</H1><br />
The Wikipedia API makes it possible to interact with Wikipedia/Mediawiki through a webservice instead of the normal browserbased web interface.</p>
<div class="is_note">
The documentation for using this api is at <a href="http://www.mediawiki.org/wiki/API">http://www.mediawiki.org/wiki/API</a>.<br />
The specific documentation for the English Wikipedia(the mediawiki api can be called on all Wikimedia sites, so not just Wikipedia itself, but also Wikimedia Commons etc..) is at <a href="http://en.wikipedia.org/w/api.php">http://en.wikipedia.org/w/api.php</a>.
</div>
<p>We cover a basic use case: getting the contents of the &#8220;Web service&#8221; article.</p>
<p>To fetch the contents for this article, the following url suffices:</p>
<pre class="is_code">
http://en.wikipedia.org/w/api.php? format=xml&#038;action=query&#038;titles=Web%20service&#038;prop=revisions&#038;rvprop=content
</pre>
<p>A request to this url will return an xml document which includes the current wiki markup for the page titled &#8220;Web service&#8221;. As the request parameters indicate, these requests are highly configurable. For example, other formats than xml, such as json, are possible. For a full list of available parameters, visit <a href="http://en.wikipedia.org/w/api.php">http://en.wikipedia.org/w/api.php</a>.</p>
<p>We are not going to construct these urls ourselves. We are going to use <a href="http://code.google.com/p/gwtwiki/">bliki, the Java wikipedia API library</a> instead.</p>
<h1>Getting the Java Wikipedia API lib</h1>
<p>If you are using Maven you need to add the following repository to your pom:</p>
<pre class="is_code">
&lt;repository&gt;
  &lt;id&gt;info-bliki-repository&lt;/id&gt;
  &lt;url&gt;http://gwtwiki.googlecode.com/svn/maven-repository/&lt;/url&gt;
  &lt;releases&gt;
    &lt;enabled&gt;true&lt;/enabled&gt;
  &lt;/releases&gt;
&lt;/repository&gt;
</pre>
<p>together with the following dependency:</p>
<pre class="is_code">
&lt;!-- bliki --&gt;
&lt;dependency&gt;
  &lt;groupId&gt;info.bliki.wiki&lt;/groupId&gt;
  &lt;artifactId&gt;bliki-core&lt;/artifactId&gt;
  &lt;version&gt;3.0.17&lt;/version&gt;
&lt;/dependency&gt;
</pre>
<p>and if you want the addons:</p>
<pre class="is_code">
&lt;dependency&gt;
  &lt;groupId&gt;info.bliki.wiki&lt;/groupId&gt;
  &lt;artifactId&gt;bliki-addons&lt;/artifactId&gt;
  &lt;version&gt;3.0.17&lt;/version&gt;
&lt;/dependency&gt;
</pre>
<p>If you are not using Maven, just grab the jar from <a href="http://code.google.com/p/gwtwiki/">the linked project page</a>.</p>
<p>Usage examples of this lib are at <a href="http://code.google.com/p/gwtwiki/wiki/HTML2Mediawiki">http://code.google.com/p/gwtwiki/wiki/HTML2Mediawiki</a>.</p>
<h1>Basic example: getting the contents of an article</h1>
<p>However, the basic usage example given in the documentation, at this time, does not compile with the current version of the lib.<br />
Therefore, we will start with a basic usage example of which no variant is listed there and extend this example.</p>
<p>We are going to list the code to fetch the content of the &#8220;Web service&#8221; page and render it as html. Note that to get a specific page, you need to know its title.<br />
If the page does not exist, a result with one empty page will be returned.<br />
For ambiguous titles, the disambiguation page will be given too, so even if you get a non-empty result, you still need to check it thoroughly.</p>
<pre class="is_code">
String[] listOfTitleStrings = { "Web service" };
User user = new User("", "", "http://en.wikipedia.org/w/api.php");
user.login();
List&lt;Page&gt; listOfPages = user.queryContent(listOfTitleStrings);
for (Page page : listOfPages) {
  WikiModel wikiModel = new WikiModel("${image}", "${title}");
  String html = wikiModel.render(page.toString());
  System.out.println(html);
}
</pre>
<p>We are instantiating a user on the English wikipedia endpoint. Since we are only going to read, we can login anonymously.<br />
We query the english Wikipedia for the specified titles and get one page as result in the listOfPages variable.<br />
We then instantiate a WikiModel. This class will render the html and its constructor parameters &#8211; imageBaseUrl and linkBaseUrl &#8211; determine where the rendered images and links will point too. For example, if you want these to point to local files, you would supply a local path. In the example, I made it completely relative. In the official documentation, these are &#8220;http://www.mywiki.com/wiki/${image}&#8221; and &#8220;http://www.mywiki.com/wiki/${title}&#8221;, which you would use if you were putting a Wikipedia copy at http://www.mywiki.com/wiki/.<br />
We then render the page as html and print it out to the console.</p>
<p>The outputted rendering is very rudimentary and is far from complete though:</p>
<ul>
<li><a href="http://www.mediawiki.org/wiki/Help:Magic_words">Wikipedia magic variables</a>, recognizable by their {{&#8230;}} markup, are not rendered. Instead, they are displayed literally.</li>
<li>By default, all markup is rendered. However, you might need to leave certain parts out or modify the content a bit before it is displayed for your particular use case.</li>
</ul>
<h1>Handling magic variables</h1>
<p>Most <a href="http://www.mediawiki.org/wiki/Help:Magic_words">magic words</a> are not supported by the Java Wikipedia API.<br />
We need to implement their rendering ourselves.<br />
If you want to do some advanced converting of the Wikipedia content, such as handling these magic words, you need to extend the WikiModel class. More info about this is at <a href="http://code.google.com/p/gwtwiki/wiki/Mediawiki2HTML">http://code.google.com/p/gwtwiki/wiki/Mediawiki2HTML</a>.</p>
<p>This is what we are doing here:</p>
<pre class="is_code">
package com.integratingstuff.wikimedia;

import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

import info.bliki.wiki.model.Configuration;
import info.bliki.wiki.model.WikiModel;
import info.bliki.wiki.namespaces.INamespace;

public class MyWikiModel extends WikiModel{

  public MyWikiModel(Configuration configuration, Locale locale,
    String imageBaseURL, String linkBaseURL) {
      super(configuration, locale, imageBaseURL, linkBaseURL);
  }
  public MyWikiModel(Configuration configuration,
    ResourceBundle resourceBundle, INamespace namespace,
    String imageBaseURL, String linkBaseURL) {
      super(configuration, resourceBundle, namespace, imageBaseURL, linkBaseURL);
  }
  public MyWikiModel(Configuration configuration, String imageBaseURL,
    String linkBaseURL) {
      super(configuration, imageBaseURL, linkBaseURL);
  }
  public MyWikiModel(String imageBaseURL, String linkBaseURL) {
    super(imageBaseURL, linkBaseURL);
  }

  @Override
  public String getRawWikiContent(String namespace, String articleName,
    Map&lt;String, String&gt; templateParameters) {
      String rawContent = super.getRawWikiContent(namespace, articleName, templateParameters);

      if (rawContent == null){
        return "";
      }
      else {
        return rawContent;
      }
    }
}
</pre>
<p>The overriden getRawWikiContent in the above MyWikiModel code returns null for most magic words in its default implementation. A magic word such as {{InfoBox}} would pass through this code with the default namespace=&#8221;Template&#8221; and articleName=&#8221;InfoBox&#8221;. If null is returned, the magic word will be outputted in the rendered html as is(so for {{InfoBox}}, this would be {{InfoBox}}). So, the resulting html is full of these unreadable tags, which does not make it look pretty printed.<br />
What we are doing in the above code to solve this is returning &#8220;&#8221; instead of null, so the magic word does not get rendered at all.<br />
Nothing is stopping you from returning something else though.</p>
<h1>Controlling the rendering of the html by implementing an ITextConverter</h1>
<p>For my particular use case, I also did not want to render any html links, I did not want to render any references and I did not want to render any images. The WikiModel class does not implement support for leaving out these things. However, the overloaded render method of WikiModel can take an ITextConverter object as an argument, the object that is responsible for converting the parsed nodes to html(or another format, like pdf or plain text). The default ITextConverter, used when none is specified as an argument, is HTMLConverter, with its property noLinks set to false by default.<br />
However, there is a HTMLConverter constructor which sets the noLinks boolean. By passing true to this constructor, no links will be rendered. Their content will be rendered as plain text instead.<br />
Since I still had to leave out the reference and image elements, I still ended up subclassing the <a href="http://code.google.com/p/gwtwiki/source/browse/trunk/info.bliki.wiki/bliki-core/src/main/java/info/bliki/wiki/filter/HTMLConverter.java?r=530&#038;spec=svn530">HTMLConverter</a>.<br />
First, I made a more extensible version of it:</p>
<pre class="is_code">
package com.ceardannan.exams.wikimedia;

import info.bliki.htmlcleaner.ContentToken;
import info.bliki.htmlcleaner.EndTagToken;
import info.bliki.htmlcleaner.TagNode;
import info.bliki.htmlcleaner.Utils;
import info.bliki.wiki.filter.HTMLConverter;
import info.bliki.wiki.model.Configuration;
import info.bliki.wiki.model.IWikiModel;
import info.bliki.wiki.model.ImageFormat;
import info.bliki.wiki.tags.HTMLTag;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * A converter which renders the internal tree node representation as specific
 * HTML text, but which is easier to change in behaviour than its superclass and
 * has a noImages property, which can be set to leave out all images
 *
 */
public class ExtendedHtmlConverter extends HTMLConverter {

  private boolean noImages;

  public ExtendedHtmlConverter() {
    super();
  }

  public ExtendedHtmlConverter(boolean noLinks) {
    super(noLinks);
  }

  public ExtendedHtmlConverter(boolean noLinks, boolean noImages) {
    this(noLinks);
    this.noImages = noImages;
  }

  protected void renderContentToken(Appendable resultBuffer,
      ContentToken contentToken, IWikiModel model) throws IOException {
    String content = contentToken.getContent();
    content = Utils.escapeXml(content, true, true, true);
    resultBuffer.append(content);
  }

  protected void renderHtmlTag(Appendable resultBuffer, HTMLTag htmlTag,
      IWikiModel model) throws IOException {
    htmlTag.renderHTML(this, resultBuffer, model);
  }

  protected void renderTagNode(Appendable resultBuffer, TagNode tagNode,
      IWikiModel model) throws IOException {
    Map&lt;String, Object&gt; map = tagNode.getObjectAttributes();
    if (map != null &#038;&#038; map.size() &gt; 0) {
      Object attValue = map.get("wikiobject");
      if (!noImages) {
        if (attValue instanceof ImageFormat) {
          imageNodeToText(tagNode, (ImageFormat) attValue, resultBuffer, model);
        }
      }
    } else {
      nodeToHTML(tagNode, resultBuffer, model);
    }
  }

  public void nodesToText(List&lt;? extends Object&gt; nodes,
      Appendable resultBuffer, IWikiModel model) throws IOException {
    if (nodes != null &#038;&#038; !nodes.isEmpty()) {
      try {
        int level = model.incrementRecursionLevel();

        if (level &gt; Configuration.RENDERER_RECURSION_LIMIT) {
          resultBuffer
              .append("&lt;span class=\"error\"&gt;Error - recursion limit exceeded rendering tags in HTMLConverter#nodesToText().&lt;/span&gt;");
          return;
        }
        Iterator&lt;? extends Object&gt; childrenIt = nodes.iterator();
        while (childrenIt.hasNext()) {
          Object item = childrenIt.next();
          if (item != null) {
            if (item instanceof List) {
              nodesToText((List) item, resultBuffer, model);
            } else if (item instanceof ContentToken) {
              // render plain text content
              ContentToken contentToken = (ContentToken) item;
              renderContentToken(resultBuffer, contentToken, model);
            } else if (item instanceof HTMLTag) {
              HTMLTag htmlTag = (HTMLTag) item;
              renderHtmlTag(resultBuffer, htmlTag, model);
            } else if (item instanceof TagNode) {
              TagNode tagNode = (TagNode) item;
              renderTagNode(resultBuffer, tagNode, model);
            } else if (item instanceof EndTagToken) {
              EndTagToken node = (EndTagToken) item;
              resultBuffer.append('&lt;');
              resultBuffer.append(node.getName());
              resultBuffer.append("/&gt;");
            }
          }
        }
      } finally {
        model.decrementRecursionLevel();
      }
    }
  }

  protected void nodeToHTML(TagNode node, Appendable resultBuffer,
      IWikiModel model) throws IOException {
    super.nodeToHTML(node, resultBuffer, model);
  }

}
</pre>
<p>The functionality of the above HTMLConverter is almost the same as the original one, but the code is divided into more methods, for easier overriding, and a noImages boolean is added as well, which leaves out all the images at render time if set to true.</p>
<p>And then I subclassed this class like this:</p>
<pre class="is_code">
package com.ceardannan.exams.wikimedia;

import info.bliki.htmlcleaner.ContentToken;
import info.bliki.htmlcleaner.Utils;
import info.bliki.wiki.model.IWikiModel;
import info.bliki.wiki.tags.HTMLTag;

import java.io.IOException;

public class MyHtmlConverter extends ExtendedHtmlConverter {

  public MyHtmlConverter() {
    super();
  }

  public MyHtmlConverter(boolean noLinks) {
    super(noLinks);
  }

  public MyHtmlConverter(boolean noLinks, boolean noImages) {
    super(noLinks, noImages);
  }

  protected void renderContentToken(Appendable resultBuffer,
      ContentToken contentToken, IWikiModel model) throws IOException {
    String content = contentToken.getContent();
    content = content.replaceAll("\\(,", "(").replaceAll("\\(\\)", "()");
    content = Utils.escapeXml(content, true, true, true);
    resultBuffer.append(content);
  }

  protected void renderHtmlTag(Appendable resultBuffer, HTMLTag htmlTag,
      IWikiModel model) throws IOException {
    String tagName = htmlTag.getName();
    if ((!tagName.equals("ref"))) {
      super.renderHtmlTag(resultBuffer, htmlTag, model);
    }
  }
}
</pre>
<p>If the converter encounters a &#8220;ref&#8221; html tag, it does not render the html tag. This results in no references getting rendered at all.<br />
I also changed the rendering of the content a bit. This is because returning of &#8220;&#8221; for the magic words(see above), might leave (, or () in the text, and the line that replaces these cleans up the rendered html.</p>
<p>The code that we call to get the html is now:</p>
<pre class="is_code">
MyWikiModel wikiModel = new MyWikiModel("${image}", "${title}");
String currentContent = page.getCurrentContent();
String html = wikiModel.render(
  new MyHtmlConverter(true, true), currentContent);
</pre>
<h1>The end result</h1>
<p>We now have a properly formatted, completely offline article, with all its external links, images and references stripped:</p>
<p><a href="http://www.integratingstuff.com/wp-content/uploads/2012/04/wiki_to_html.png"><img src="http://www.integratingstuff.com/wp-content/uploads/2012/04/wiki_to_html-300x226.png" alt="" title="Wiki To Html" width="300" height="226" class="aligncenter size-medium wp-image-630" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.integratingstuff.com/2012/04/06/hook-into-wikipedia-using-java-and-the-mediawiki-api/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>iOS design tips and tricks</title>
		<link>http://www.integratingstuff.com/2012/03/03/ios-design-tips-and-tricks/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=ios-design-tips-and-tricks</link>
		<comments>http://www.integratingstuff.com/2012/03/03/ios-design-tips-and-tricks/#comments</comments>
		<pubDate>Sat, 03 Mar 2012 16:00:59 +0000</pubDate>
		<dc:creator>Steffen Luypaert</dc:creator>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[objective-C]]></category>
		<category><![CDATA[UIView]]></category>
		<category><![CDATA[XCode]]></category>

		<guid isPermaLink="false">http://www.integratingstuff.com/?p=592</guid>
		<description><![CDATA[I have been doing some iOS development again lately, and I am writing some posts about what I have learned. The previous post covered some general tips, this one is going to be about design/interface tips for some common iOS classes.

This article is for people who played around in XCode and objectiveC already, and are familiar with the basic iOS UIView and related classes.]]></description>
			<content:encoded><![CDATA[<p>I have been doing some iOS development again lately, and I am writing some posts about what I have learned. The previous post covered some general tips, this one is going to be about design/interface tips for some common iOS classes.</p>
<p>This article is for people who played around in XCode and objectiveC already, and are familiar with the basic iOS UIView and related classes.</p>
<h1>Thanks!</h1>
<p>The project these tips are applied to are my language classes for iPhone and iPad, such as <a href="http://itunes.apple.com/app/spanish-class-lite/id422600410">Spanish Class</a>, <a href="http://itunes.apple.com/app/french-class-lite/id423788470">French Class</a> and <a href="http://itunes.apple.com/app/german-class-lite/id496024463">German Class</a>. If you want to thank me for this article, please download a free version, and send me your feedback or give it a 4 or 5 star rating if you like the app.</p>
<h1>Tip 1 &#8211; UIView: drawing an image as a background</h1>
<p>Although you can not set an image as the background of a UIView in an interface builder xib file, it is easy to load the image as a color and assign it as the backgroundcolor to a view:</p>
<pre class="is_code">
UIView *mainView = self.view;
mainView.backgroundColor = [UIColor colorWithPatternImage:
     [UIImage imageNamed: @"languages-menu.png"]];
</pre>
<p>Which results in the following background for the main menu UIView of the languages app:</p>
<p><a href="http://www.integratingstuff.com/wp-content/uploads/2012/02/overlay.png"><img src="http://www.integratingstuff.com/wp-content/uploads/2012/02/overlay-200x300.png" alt="" title="iOS UIView Overlay" width="200" height="300" class="aligncenter size-medium wp-image-594" /></a></p>
<h1>Tip 2 &#8211; UIButton: fixing the position of the image and the label within</h1>
<p>As shown in the screenshot above, I wanted to put the image and text within a main menu button at a specific location, so the images in the 10 different buttons would appear symmetric to each other.</p>
<p>This is very easy to do with the following method:</p>
<pre class="is_code">
- (void) fixButton:(UIButton *) button{
    //positioning
    UIImageView *imageView = button.imageView;
    UILabel *label = button.titleLabel;

    CGRect imageFrame = imageView.frame;
    CGRect labelFrame = label.frame;

    imageFrame.origin.x = 10;
    labelFrame.origin.x = 10 + imageFrame.size.width + 5;

    imageView.frame = imageFrame;
    label.frame = labelFrame;
}
</pre>
<p>We are changing the x values of the origin of the frames of the two views within the button, making the image start at x coordinate 10 within the UIButton, and putting the label next to it, with only 5 pixels in between.</p>
<p>The key thing to realize here is that every view &#8211; UIView and subclasses like UITableView, UIButton,&#8230; &#8211; are positioned on the screen the same way: they have a frame, with an origin with an x and an y coordinate and a size with a width and a length. Changing their values is easy, and not considered bad practice.<br />
Unlike as for Android, where you want to use relative layouts to accomodate for the wide range of possible screen sizes and shapes, playing with these values is common practice on iOS, since you know everything about the screensize. There are only 4 possible resolutions anyway: landscape and portrait, both for iPhone and iPad.</p>
<div class="is_note">
Note: One more thing about UIButtons that beats me is why Apple didnt provide an easy way to change the coloring of the basic white button. You need to use either the white button, use an image(which means firing up Adobe Illustrator) or some complicated way of putting a view on top of the image and masking it. Apple, please add plain recoloring of buttons!
</div>
<h1 style="padding-top: 10px;">Tip 3 &#8211; UITableView: clearing the background of a table</h1>
<p>In the exercises screens, I wanted to present the questions on a schoolboard interface, as if the questions and possible answers were written on the schoolboard. The list of possible answers is wrapped in a UITableView, so it is easy to change the number of answers(they used to be presented as a UIPicker, but that just looked awful, and there is no way to achieve the below effect with a picker anyway). </p>
<p><a href="http://www.integratingstuff.com/wp-content/uploads/2012/02/schoolboard.png"><img src="http://www.integratingstuff.com/wp-content/uploads/2012/02/schoolboard-200x300.png" alt="" title="iOS UITableView without background" width="200" height="300" class="aligncenter size-medium wp-image-596" /></a></p>
<p>To do this, I had to manually clear the background of the tableview, which I implemented as <a href="https://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/chapters/occategories.html">an Objective-C category</a>:</p>
<pre class="is_code">
#import "UITableView+RemoveBackgroundFromTable.h"

@implementation UITableView (RemoveBackgroundFromTable)

-(void) removeBackgroundFromTable{
    self.backgroundColor = [UIColor clearColor];
    self.opaque = NO;
    self.backgroundView = nil;
}

@end
</pre>
<p>The first two lines can be set in a xib file, by unchecking &#8220;opaque&#8221; and by setting the color of the UITableView to &#8220;clearColor&#8221;. The last line cannot be done in a xib file though and is necessary as well. Not only the backgroundColor needs to be set to transparant, the backgroundView of the UITableView needs to be set to nil as well.</p>
<h1>Tip 4 &#8211; UITableview: showing cells with dynamic height</h1>
<p>When doing iOS development, you will want to tamper with the height of cells sooner or later. The UITableViewCells do not adjust their height automatically, and when the cell spans a few sentences, you cannot set the height in advance, because you just dont know it.</p>
<p>Credit were credit is due, <a href="http://www.raddonline.com/blogs/geek-journal/iphone-sdk-resizing-a-uitableviewcell-to-hold-variable-amounts-of-text/">this post describes exactly how to resize cells to accommodate different cell heights</a>. However, since I was working with my own UITableViewCell subclasses which usually had another view to the left, I had to rewrite the StringHelper category a bit and add an xOffset:</p>
<pre class="is_code">
@implementation NSString (StringHelper)

- (CGFloat)RAD_textHeightForSystemFontOfSize:(CGFloat)size xOffset:(int) xOffset{
    //Calculate the expected size based on the font and linebreak mode of the label
    CGFloat maxWidth = [UIScreen mainScreen].bounds.size.width - 25 - xOffset;
    CGFloat maxHeight = 9999;
    CGSize maximumLabelSize = CGSizeMake(maxWidth,maxHeight);

    CGSize expectedLabelSize = [self sizeWithFont:[UIFont systemFontOfSize:size] constrainedToSize:maximumLabelSize lineBreakMode:UILineBreakModeWordWrap];

    return expectedLabelSize.height;
}

- (CGRect)RAD_frameForCellLabelWithSystemFontOfSize:(CGFloat)size xOffset:(int) xOffset{
    CGFloat width = [UIScreen mainScreen].bounds.size.width - 25 - xOffset;
    CGFloat height = [self RAD_textHeightForSystemFontOfSize:size xOffset:xOffset] + 10.0;
    return CGRectMake(10.0f+xOffset, 10.0f, width, height);
}

- (void)RAD_resizeLabel:(UILabel *)aLabel WithSystemFontOfSize:(CGFloat)size xOffset:(int) xOffset{
    aLabel.frame = [self RAD_frameForCellLabelWithSystemFontOfSize:size xOffset:xOffset];
    aLabel.text = self;
    [aLabel sizeToFit];
}

@end
</pre>
<p>To make sure the cell resizes properly, it is then only necessary to resize the UILabel in your tableView: cellForRowAtIndexPath: method:</p>
<pre class="is_code">
- (UITableViewCell *)tableView:(UITableView *)tableView
		 cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        CustomCell *cell = [self getCustomCell];
        NSUInteger row = [indexPath row];

        NSString *element = [list objectAtIndex:row];

        cell.customLabel.numberOfLines = 0;
        [element RAD_resizeLabel:cell.inTargetLanguage WithSystemFontOfSize:17 xOffset:40.0];

        CGRect secondFrame = cell.customLabel.frame;
        secondFrame.origin.y = secondFrame.origin.y + cell.customLabel.frame.size.height + 10;
        cell.customLabel.frame = secondFrame;

        return cell;
}
</pre>
<p>and to calculate the height, in the tableView:heightForRowAtIndexPath: method:</p>
<pre class="is_code">
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath  {
	NSUInteger row = [indexPath row];
        NSString *element = [list objectAtIndex:row];
        CGFloat height = [element RAD_textHeightForSystemFontOfSize:17 xOffset:40.0] + 10.0;
        return height;
}
</pre>
<h1>Tip 5 &#8211; UIFont: using the new fancy fonts but providing a callback if they are not available</h1>
<p>iOS provides two chalk fonts, and I wanted to use any of those for the schoolboard: ChalkDuster and ChalkboardSE. However, these fonts are not available on all iOS devices.</p>
<p>Therefore, I check which ones are available in a FontUtil class and return accordingly: </p>
<pre class="is_code">
+(UIFont*) getChalkFontWithSize:(int) size{
    if ([[UIFont fontNamesForFamilyName:@"ChalkDuster"] count] > 0){
        if ([[UIFont fontNamesForFamilyName:@"ChalkDuster"] containsObject:@"ChalkDuster"]){
            return [UIFont fontWithName:@"ChalkDuster" size:size];
        }
        else {
            return [[UIFont fontNamesForFamilyName:@"ChalkDuster"] objectAtIndex:0];
        }
    }
    else if ([[UIFont fontNamesForFamilyName:@"Chalkboard SE"] count] > 0){
        if ([[UIFont fontNamesForFamilyName:@"ChalkboardSE-Regular"] containsObject:@"ChalkboardSE-Regular"]){
            return [UIFont fontWithName:@"ChalkboardSE-Regular" size:size];
        }
        else {
            return [[UIFont fontNamesForFamilyName:@"Chalkboard SE"] objectAtIndex:0];
        }
    }
    else {
        return [UIFont systemFontOfSize:size];
    }
}
</pre>
<p>Another tip: to have a quick overview of all the iOS fonts, check <a href="http://www.iosfonts.com">www.iosfonts.com</a>.</p>
<h1>Tip 6 &#8211; UIColor: getting a color from an hex string</h1>
<p>If you want to port an app from Android &#8211; we are integrating stuff here after all -, where colors are defined in their rgb values, <a href="http://stackoverflow.com/questions/4265161/how-to-convert-hexadecimal-to-rgb">this Stackoverflow Question gives a nice category on UIColor</a>, which makes it possible to call:</p>
<pre class="is_code">
[UIColor: colorWithHexString: @"#800000"]
</pre>
<p>returning a UIColor matching the hex rgb string.</p>
<h1>Tip 7 &#8211; UIAlertView: recoloring the alert</h1>
<p>To recolor the basic blue UIAlertView, you need to subclass it and override layoutSubViews. Again, I do not get why Apple did not build this feature into XCode, since it seems to me something a lot of developers want to do.</p>
<p><a href="http://kwigbo.com/post/318396305/iphone-sdk-custom-uialertview-background-color">This blog post gives an excellent implementation of such a CustomAlertView</a>.</p>
<p>You can then just set the color to #80000 or black to get a darkred or black color like this:</p>
<pre class="is_code">
-(void) showRedAlert: (NSString *) message andTitle:(NSString *) title{
    [CustomAlertView setBackgroundColor:[UIColor colorWithHexString:@"800000"]
                        withStrokeColor:[UIColor whiteColor]];
	UIAlertView *alert = [[CustomAlertView alloc] initWithTitle:title
                                                        message:message delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
	[alert show];
	[alert release];
}
</pre>
<p>Resulting in alertviews looking like this:</p>
<table>
<tr>
<td>
<a href="http://www.integratingstuff.com/wp-content/uploads/2012/02/red_alert.png"><img src="http://www.integratingstuff.com/wp-content/uploads/2012/02/red_alert.png" alt="" title="Red UIAlertView" width="282" height="239" class="aligncenter size-full wp-image-598" /></a>
</td>
<td>
<a href="http://www.integratingstuff.com/wp-content/uploads/2012/02/black_alert.png"><img src="http://www.integratingstuff.com/wp-content/uploads/2012/02/black_alert.png" alt="" title="Black UIAlertView" width="282" height="200" class="aligncenter size-full wp-image-599" /></a>
</td>
</tr>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.integratingstuff.com/2012/03/03/ios-design-tips-and-tricks/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Some iOS development tips</title>
		<link>http://www.integratingstuff.com/2012/02/25/some-ios-development-tips/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=some-ios-development-tips</link>
		<comments>http://www.integratingstuff.com/2012/02/25/some-ios-development-tips/#comments</comments>
		<pubDate>Sat, 25 Feb 2012 08:00:40 +0000</pubDate>
		<dc:creator>Steffen Luypaert</dc:creator>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[iOS Game Center]]></category>
		<category><![CDATA[iRate]]></category>
		<category><![CDATA[objective-C]]></category>
		<category><![CDATA[XCode]]></category>

		<guid isPermaLink="false">http://www.integratingstuff.com/?p=581</guid>
		<description><![CDATA[I have been doing some iOS development again lately, and in the following two posts I am going to share a few things that I have learned. This first one is going to cover some general tips.

This article is for people who played around in XCode and objectiveC already.]]></description>
			<content:encoded><![CDATA[<p>I have been doing some iOS development again lately, and in the following two posts I am going to share a few things that I have learned. This first one is going to cover some general tips.</p>
<p>This article is for people who played around in XCode and objectiveC already.</p>
<h1>Tip 1: Learn to debug zombies</h1>
<p>This section is useless to people using automatic reference counting(arc). However, there are still some reasons not to use arc, as discussed in <a href="http://longweekendmobile.com/2011/09/07/objc-automatic-reference-counting-in-xcode-explained/">this article on arc</a>, and this section is aimed at the people that can not migrate just yet.</p>
<p>Especially when coming from a Java background where you are not used to release taken memory manually, you will make some allocation/releasing error sooner or later. </p>
<p>Note that when an instance is released, it becomes a zombie, and no method should be called on it anymore.</p>
<p>A common beginner mistake is to replace </p>
<pre class="is_code">
[NSMutableArray new]
</pre>
<p>with something like </p>
<pre class="is_code">
[NSMutableArray arrayWithArray: ...]
</pre>
<p>without modifying any other code for example.</p>
<p>When using new, the instance is not autoreleased; when using arrayWithArray, it is. You probably added a release statement companying the first statement. For the second statement you need to remove that release statement.</p>
<p>Unless the array is still needed later, with which the autorelease mechanism of the second statement might release it too early, requiring you to retain it, and still release it manually later.</p>
<p>Anyway, all of this is not too bad, but you have to learn how to track and solve these errors. By default, XCode will just make the simulator crash with a EXC_BAD_ACCESS, without giving any other information.</p>
<p>The first and most important thing to do is to press ALT-CMD-R in XCode, which will bring up the schemes screen:</p>
<p><a href="http://www.integratingstuff.com/wp-content/uploads/2012/02/enable_zombies.png"><img src="http://www.integratingstuff.com/wp-content/uploads/2012/02/enable_zombies-300x204.png" alt="" title="Enabling Zombies" width="300" height="204" class="aligncenter size-medium wp-image-583" /></a></p>
<p>Make sure you &#8220;Enable Zombie Objects&#8221; there and then run the app again. Reproduce the error. In the XCode output, a clear message will now be logged:</p>
<pre class="is_code">
-[__NSArrayM release]: message sent to deallocated instance 0xc41d7e0
</pre>
<p>which is what we get if we just replace the [NSMutableArray new] with [NSMutableArray arrayWithArray:], without removing the release statement that comes somewhere after the [NSMutableArray new]. Since the second variation is autoreleased, the instance is already deallocated by the time the manual release statement on the array is called.</p>
<p>The above tells you the error type and on what object type and method the error occurred. But sometimes it is unclear why a certain instance was already deallocated. To bug these more challenging errors, you should profile the app through Product&gt;Profile&gt;Zombies. </p>
<p><a href="http://www.integratingstuff.com/wp-content/uploads/2012/02/profile_zombies.png"><img src="http://www.integratingstuff.com/wp-content/uploads/2012/02/profile_zombies-300x247.png" alt="" title="Profiling zombies" width="300" height="247" class="aligncenter size-medium wp-image-584" /></a></p>
<p>When the fault occurs, the profiler blocks on the zombie object, and gives a stack of its entire lifecycle, which makes it easy to track these errors.</p>
<h1>Tip 2: Code for both iPhone and iPad</h1>
<p>When making an iOs app, make sure to have seperate screens for iPhone and iPad. The market for iPad apps is about as large as the one for iPhone apps, and no iPad user wants to use the default iPhone interface that puts an iPhone on his way bigger screen.</p>
<p>There are <a href="http://www.devx.com/wireless/Article/44472/1763/page/1">great tutorials out there to create a universal application</a>. The one thing I want to add is that it is best to isolate all device dependent code in one Util class, such as:</p>
<pre class="is_code">
#ifdef UI_USER_INTERFACE_IDIOM()
#define IS_IPAD() (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#else
#define IS_IPAD() (false)
#endif

#import "UiUtil.h"

@implementation UiUtil

+(NSString *) getNibNameFrom: (NSString*) nibBaseName{
    if (IS_IPAD()){
        NSMutableString *nibForiPad = [NSMutableString stringWithString: nibBaseName];
        [nibForiPad appendString:@"-iPad"];
        return nibForiPad;
    }
    else {
         return nibBaseName;
    }
}

+(NSString *) getBackgroundNameFrom: (NSString*) backgroundBaseName{
    if (IS_IPAD()){
        NSMutableString *backgroundForiPad = [NSMutableString stringWithString: backgroundBaseName];
        [backgroundForiPad replaceOccurrencesOfString:@".png" withString:@"-iPad.png" options:0 range:NSMakeRange(0, [backgroundForiPad length])];
        return backgroundForiPad;
    }
    else {
        return backgroundBaseName;
    }
}

+(CGFloat) getFontModifier{
    if (IS_IPAD()){
        return 2;
    }
    else {
        return 1.0;
    }
}

@end
</pre>
<p>The above UiUtil class isolates the code to fetch the different xibs, backgrounds and fontsizes for iPhone or iPad, without putting any &#8220;isiPad&#8221; methods in your code.</p>
<h1>Tip 3: Find your way to the Apple Developer examples</h1>
<p>Recently, I had to use the <a href="https://developer.apple.com/library/ios/#DOCUMENTATION/GameKit/Reference/GameKit_Collection/Introduction/Introduction.html">GameKit</a> and <a href="https://developer.apple.com/library/ios/#DOCUMENTATION/SystemConfiguration/Reference/SystemConfiguration_Utilities/Reference/reference.html">SystemConfiguration</a> APIs and I found out that Apple is making awesome examples for all the iOs frameworks available to its developers in the <a href="https://developer.apple.com/library/ios/navigation/">iOS Developer library</a>. The code in many of these examples can be reused for like 95%.</p>
<p>To integrate with the Game Center for example, you just need to download the <a href="https://developer.apple.com/library/ios/#samplecode/GKTapper/Introduction/Intro.html">GKTapper example</a> and you can reuse the GameCenterManager class in it for all your projects.<br />
All that you need to do to integrate with Game Center after importing this class is calling some submitScore and submitAchievement methods on it to send the data to the Apple servers, and instantiate GKAchievementViewController or GKLeaderboardViewController to show the achievements or leaderboard(s).</p>
<p>Writing the Game Center integration code can be done in an hour. I actually spend more time in entering the Game Center Achievements and Leaderboards in iTunes connect than I spend writing game center related code.</p>
<h1>Tip 4: Use third party libs</h1>
<p>Next to the awesome Apple developer examples, there are some great third party libs available as well, that can be used commercially.</p>
<p>One simple but great one is <a href="https://github.com/nicklockwood/iRate">iRate</a>. It enables you to ask a user for a rating on the appstore after certain conditions are met. It is easily configurable, and just consists of the iRate.h and iRate.m file.</p>
<p>You only need to put the following in your AppDelegate:</p>
<pre class="is_code">
[iRate sharedInstance].appStoreID = 422387255;
//[iRate sharedInstance].debug = YES;
</pre>
<p>where appId is the App Id of your app as shown in Itunes Connect. By default, the dialog in which a rating is asked is not shown until at least 5 days have passed since the app was installed, but if debug is set to YES, the dialog shows right away on app startup.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.integratingstuff.com/2012/02/25/some-ios-development-tips/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to create a Drupal 7 Module: introduction to Drupal modules, hooks, Drupal database API, Drupal File API and Drupal Form API</title>
		<link>http://www.integratingstuff.com/2012/01/23/how-to-create-a-drupal-7-module-introduction-to-drupal-modules-hooks-drupal-database-api-drupal-file-api-and-drupal-form-api/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=how-to-create-a-drupal-7-module-introduction-to-drupal-modules-hooks-drupal-database-api-drupal-file-api-and-drupal-form-api</link>
		<comments>http://www.integratingstuff.com/2012/01/23/how-to-create-a-drupal-7-module-introduction-to-drupal-modules-hooks-drupal-database-api-drupal-file-api-and-drupal-form-api/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 03:00:18 +0000</pubDate>
		<dc:creator>Steffen Luypaert</dc:creator>
				<category><![CDATA[Php]]></category>
		<category><![CDATA[Drupal]]></category>

		<guid isPermaLink="false">http://www.integratingstuff.com/?p=561</guid>
		<description><![CDATA[<a href="http://drupal.org/">Drupal</a> is a free and open source content management system written in <a href="http://www.php.net/">PHP</a>. The standard release of Drupal, Drupal core, contains basic features typical to content management systems, such as menu management, page layout customization and content publishing. However, its main strength are its <a href="http://drupal.org/project/Modules">community-contributed addons</a>, known as modules, which make it possible to alter and extend Drupal's capabilities to one's wishes.
This article is about implementing such a module. <a href="http://drupal.org/node/1074360">There are other good tutorials on this</a>. This one is going to cover the specific case of creating a text file on the server with the content of certain nodes every time a node is created, updated or deleted. The tutorial delves into some of the most important Drupal APIs, such as the Database, File and Form APIs.
People reading this should have added a module to a Drupal installation before and be somewhat familiar with PHP.]]></description>
			<content:encoded><![CDATA[<p><a href="http://drupal.org/">Drupal</a> is a free and open source content management system written in <a href="http://www.php.net/">PHP</a>. The standard release of Drupal, Drupal core, contains basic features typical to content management systems, such as menu management, page layout customization and content publishing. However, its main strength are its <a href="http://drupal.org/project/Modules">community-contributed addons</a>, known as modules, which make it possible to alter and extend Drupal&#8217;s capabilities to one&#8217;s wishes.<br />
This article is about implementing such a module. <a href="http://drupal.org/node/1074360">There are other good tutorials on this</a>. This one is going to cover the specific case of creating a text file on the server with the content of certain nodes every time a node is created, updated or deleted. The tutorial delves into some of the most important Drupal APIs, such as the Database, File and Form APIs.<br />
People reading this should have added a module to a Drupal installation before and be somewhat familiar with PHP.</p>
<h2>1. Drupal Modules</h2>
<p>A module is a collection of php functions that link into Drupal, providing additional functionality to the Drupal installation.<br />
Because the module code executes within the Drupal context, it can access all the variables and structures and use all the functions of Drupal core.</p>
<h3>1.1. Choose a short name</h3>
<p>The first step in creating a module is to choose a short name for it. This short name will be used in all file and function names in your module. In this example, we will be using “nodes_to_text_file” as the short name. </p>
<p>Make sure your short name starts with a letter and only contains lower-case letters and underscores. Also make sure your module does not have the same short name as any theme you will be using.</p>
<h3>1.2. Create the directory</h3>
<p>In the modules directory of your Drupal 7 install, create a folder with your short name as its name. </p>
<h3>1.3 empty module file</h3>
<p>Create a nodes_to_text_file.module file in your nodes_to_text_file directory. It is to this file that we will add the functions that will hook into Drupal. In the next section, we will add the first function.<br />
Module files begin with the opening php tag. Add it to the module file:</p>
<pre class="is_code">
&lt;?php
</pre>
<p>However, omit the closing php tag ?&gt;. Omitting it is a convention, and including it might cause strange runtime behavior on certain server setups. </p>
<h3>1.4 Creating the info file</h3>
<p>Every module has its <a href="http://drupal.org/node/171205">info file</a>. It contains metadata about the module and hence, tells Drupal about the module. Without this file, the module will not appear in the module listing of your Drupal installation.</p>
<p>Create a nodes_to_text_file.info file in your nodes_to_text_file directory:</p>
<pre class="is_code">
name = Nodes To Text File
description = A module that creates a text file containing all content of certain types of nodes whenever a node of one of these types is added, edited or deleted
core = 7.x
</pre>
<p>The above 3 properties form the minimal setup: name sets the name of the module, description describes what the module does and core determines with which version of Drupal this module is meant to be used.</p>
<p>After adding the info file, the module should be visible in your module listing. Go to Modules and scroll down to the “Other” section. The Nodes To Text File module should be listed there. Enable it.</p>
<p><a href="http://www.integratingstuff.com/wp-content/uploads/2012/01/drupal_module_listing.png"><img src="http://www.integratingstuff.com/wp-content/uploads/2012/01/drupal_module_listing-300x154.png" alt="" title="Drupal Module Listing" width="300" height="154" class="aligncenter size-medium wp-image-567" /></a></p>
<h2>2. Module Hooks</h2>
<p>Hooks are the most important concept to grasp when implementing Drupal modules. Hooks provide the points at which you can insert your actions. They can be thought of as event listeners. An event such as deleting a node would trigger the hook &#8220;hook_node_delete&#8221;. In this case, Drupal will scan all modules for functions with the name mymodule_node_delete, where mymodule is the module&#8217;s name. If your module implements hook_node_delete, that function will always execute after a node gets deleted.</p>
<p>For a list of all available hooks in Drupal core, check <a href="http://api.drupal.org/api/drupal/includes--module.inc/group/hooks/7">the Drupal 7 hooks documentation</a>.</p>
<h3>2.1 Implementing the hook_help hook</h3>
<p>The first hook we are going to implement is <a href="http://api.drupal.org/api/drupal/modules--help--help.api.php/function/hook_help/7">hook_help</a>. This hook should always be implemented. It provides help and information about the module. To implement an hook, you need to replace &#8220;hook&#8221; in the hook name(f.e. hook_help) with your module&#8217;s short name and create a function in the .module file with that name.<br />
In this case, nodes_to_text_file_help:</p>
<pre class="is_code">
/**
 * Implements hook_help.
 *
 * Displays help and module information.
 *
 * @param path
 *   Which path of the site we're using to display help
 * @param arg
 *   Array that holds the current path as returned from arg() function
 */
function nodes_to_text_file_help($path, $arg) {
  switch ($path) {
    case "admin/help#nodes_to_text_file":
      return '&lt;p&gt;'.  t("A module that creates a text file containing all content of certain types of nodes whenever a node of one of these types is added, edited or deleted") .'&lt;/p&gt;';
      break;
  }
}
</pre>
<p>The path parameter contains the information about where the user is currently at. If the user is currently at the help section of our module, we return a paragraph that gives information about our module. Note that we use the Drupal <a href="http://api.drupal.org/api/drupal/includes--bootstrap.inc/function/t/7">t($string)</a> function, which translates the content if possible and which should be used on any string that is shown to the user.</p>
<p>Now, check Modules page of your Drupal site again. You should see a link &#8216;Help&#8217; on the right of your module. If you click it, you will see the paragraph returned by the nodes_to_text_file_help function of our module.</p>
<h3>2.2. Implementing the hooks hook_node_insert, hook_node_update and hook_node_delete</h3>
<p>We will now implement the hooks <a href="http://api.drupal.org/api/drupal/modules--node--node.api.php/function/hook_node_insert/7">hook_node_insert</a>, <a href="http://api.drupal.org/api/drupal/modules--node--node.api.php/function/hook_node_update/7">hook_node_update</a> and <a href="http://api.drupal.org/api/drupal/modules--node--node.api.php/function/hook_node_delete/7">hook_node_delete</a>.<br />
All these hooks will call the same function nodes_to_text_file_write_file($node):</p>
<pre class="is_code">
/**
 * Implements hook_node_delete.
 */
function nodes_to_text_file_node_delete($node){
	nodes_to_text_file_write_file($node);
}

/**
 * Implements hook_node_update.
 */
function nodes_to_text_file_node_update($node){
	nodes_to_text_file_write_file($node);
}

/**
 * Implements hook_node_insert.
 */
function nodes_to_text_file_node_insert($node){
	nodes_to_text_file_write_file($node);
}
</pre>
<p>For now, add the following implementation of the function:</p>
<pre class="is_code">
function nodes_to_text_file_write_file($node){
	watchdog('We should write the file again!','Info Message');
}
</pre>
<p><a href="http://api.drupal.org/api/drupal/includes--bootstrap.inc/function/watchdog/7">watchdog</a> is a useful function to debug hooks. They will be added to your Drupal server logging at Reports&gt;Recent log messages:</p>
<p>&lt;watchdog screenshot&gt;</p>
<h2>3. Database API</h2>
<p>For this app, we will need two queries. One that fetches all the published nodes of the given content types of which the user is the owner:</p>
<pre class="is_code">
/**
 * Custom content function.
 *
 * Retrieve data from database
 *
 * @return
 *   A result set of the targeted nodes.
 */
function nodes_to_text_file_contents($contentTypes){
  //Use Database db_select API to retrieve nodes.
  global $user;
  $uid = $user-&gt;uid;

  $queryResult = db_select('node', 'n')
    -&gt;fields('n', array('nid', 'title', 'created'))
    -&gt;condition('uid', $uid) //owner is current user.
    -&gt;condition('status', 1) //Published.
    -&gt;condition('type', $contentTypes, 'in') //Node type is in $contentTypes
    -&gt;orderBy('created', 'DESC') //Most recent first.
    -&gt;execute();
  return $queryResult;
}
</pre>
<p>This query uses the new(starting from Drupal 7) <a href="http://api.drupal.org/api/drupal/includes--database--database.inc/function/db_query/7">db_select</a> function of the Database API. Other than the old <a href="http://api.drupal.org/api/drupal/includes--database--database.inc/function/db_query/7">db_query</a> function, db_select makes it possible to construct the query in an object oriented matter.</p>
<p><strong>db_select</strong> maps to a sql select statement(as do <a href="http://api.drupal.org/api/drupal/includes--database--database.inc/function/db_insert/7">db_insert</a>, <a href="http://api.drupal.org/api/drupal/includes--database--database.inc/function/db_update/7">db_update</a> and <a href="http://api.drupal.org/api/drupal/includes--database--database.inc/function/db_delete/7">db_delete</a> map to their sql equivalents). It takes a table name(f.e. &#8216;node&#8217;) and an alias (f.e. &#8216;n&#8217;) as its arguments. This comes down to:</p>
<pre class="is_code">
select * from node as n
</pre>
<p><strong>fields</strong> selects the fields listed in the array in its second argument on the alias n:</p>
<pre class="is_code">
select nid, title, created from node as n
</pre>
<p><strong>condition</strong> adds a condition to the query. The first is the field, the second the value, the third the operator:</p>
<pre class="is_code">
select nid, title, created from node as n where published = 1 and type in ('article','page') and uid = 1
</pre>
<p>if the values in the $contentTypes array are &#8216;article&#8217; and &#8216;page&#8217; and user Steffen has uid 1. Note that the “global $user” statement gets the global $user variable, which contains all information about the user that is currently logged in.</p>
<p><strong>orderBy</strong> then sort the results according to the field in its first argument:</p>
<pre class="is_code">
select nid, title, created from node as n where published = 1 and type in ('article','page') and uid = 1 order by created asc
</pre>
<p>The <strong>execute</strong> method then compiles and runs the query and returns the result.</p>
<p>The other query we need – one that fetches all content types of the core <a href="http://api.drupal.org/api/drupal/modules--node--node.module/7">Node Module</a> – uses the same API and is quite simular:</p>
<pre code="is_code">
/**
 * Function that retrieves the content types from the database.
 *
 * Retrieve content types from database
 *
 * @return
 *   A result set of content types.
 */
function nodes_to_text_file_retrieve_content_types(){
  $queryResult = db_select('node_type', 'nt')
    -&gt;fields('nt', array('type', 'name'))
    -&gt;condition('module', 'node') //only node content types
    -&gt;orderBy('type', 'ASC')
    -&gt;execute();
  return $queryResult;
}
</pre>
<h2>4. Drupal File API</h2>
<p>We are now implementing our nodes_to_text_file_write_file function that is called by the node_insert, node_update and node_delete hooks. We briefly discuss the part in which we determine whether the file should be written and in which we fetch the contents first.</p>
<pre class="is_code">
/**
 * Custom write file function.
 *
 * Creates the text file and stores it on the server.
 */
function nodes_to_text_file_write_file($node){
	$contentTypes = variable_get('nodes_to_text_file_content_types', array());
	$nodeType = $node-&gt;type;

	$elementFound = false;
	foreach ($contentTypes as &#038;$value) {
    	if ($nodeType === $value){
    		$elementFound = true;
    		break;
    	}
	}

	if ($elementFound){
    	$queryResult = nodes_to_text_file_contents($contentTypes);

    	global $user;
    	$username = $user-&gt;name;

   	...
}
</pre>
<p>First, we fetch the node content types which should be included in the file using <a href="http://api.drupal.org/api/drupal/includes--bootstrap.inc/function/variable_get/7">variable_get($name,$default)</a> As we will see in the next section, <a href="http://api.drupal.org/api/drupal/includes--bootstrap.inc/function/variable_set/7">variable_set($name,$value)</a> – typically invoked in a module configuration form &#8211; sets Drupal system wide variables, which can then be fetched by variable_get.<br />
We then match the node type of the node that was inserted, updated or deleted with the array of content types. If a match is found($elementFound), execution continues. We fetch the nodes using the query of the previous section and get a reference to the username of the currently logged in user.</p>
<p>Then – where the &#8230; dots are in the above function &#8211; we add the following and write out the fetched content to a file:</p>
<pre class="is_code">
	if (! file_prepare_directory(file_build_uri($username))){
    		drupal_mkdir(file_build_uri($username));
    	}

    	$filename = file_build_uri($username . '/content.txt');
    	$fh = fopen($filename, 'w') or die("can't open file");

   	 	while($record = $queryResult-&gt;fetchAssoc()) {
    		$stringData = $record['nid'] . ' - ' . $record['title'] . ' - ' . $record['created'];
    		fwrite($fh, $stringData."\n");
    	} 

    	fclose($fh);
</pre>
<p>We write the fetched contents to a context.txt file in the default Drupal public files location, in a folder with the username as its name. If this folder does not exist yet, we create it first:</p>
<pre class="is_code">
if (! file_prepare_directory(file_build_uri($username))){
   drupal_mkdir(file_build_uri($username));
}
</pre>
<p>Then we construct the filename:</p>
<pre class="is_code">
$filename = file_build_uri($username . '/content.txt');
</pre>
<p>If the username is “Steffen”, then the filename will be:<br />
&lt;drupal installation location&gt;/sites/default/files/steffen/content.txt</p>
<p>Then we open the file for writing and iterate over the queryResult. We print out the nid, the title and the created timestamp of every record to a new line in the file. We then close the file again:</p>
<pre class="is_code">
   $fh = fopen($filename, 'w') or die("can't open file");

   while($record = $queryResult-&gt;fetchAssoc()) {
      $stringData = $record['nid'] . ' - ' . $record['title'] . ' - ' . $record['created'];
      fwrite($fh, $stringData."\n");
   } 

   fclose($fh);
</pre>
<p>We are using some functions of the Drupal <a href="http://api.drupal.org/api/drupal/includes--file.inc/group/file/7">File API</a> here:<br />
<a href="http://api.drupal.org/api/drupal/includes--file.inc/function/file_build_uri/7">file_build_uri</a>: This function constructs, given a relative path, a URI into Drupal&#8217;s default files location(this is usually something like &#8216;sites/default/files/&#8217;).<br />
<a href="http://api.drupal.org/api/drupal/includes--file.inc/function/file_prepare_directory/7">file_prepare_directory</a>: This function checks that the directory exists and is writable.<br />
<a href="http://api.drupal.org/api/drupal/includes--file.inc/function/drupal_mkdir/7">drupal_mkdir</a>: This function creates a directory using Drupal&#8217;s default mode.</p>
<p>To respectively open the file for writing, write to it and close it again, we use the php functions <a href="http://php.net/manual/function.fopen.php">fopen</a>, <a href="http://php.net/manual/function.fwrite.php">fwrite</a> and <a href="http://php.net/manual/function.fclose.php">fclose</a>. </p>
<h2>5. Drupal Form API</h2>
<p>Our module is implemented now. However, we want to be able to configure the node content types for which the file should be written. We already saw that we were fetching this array of content types like this:</p>
<pre class="is_code">
$contentTypes = variable_get('nodes_to_text_file_content_types', array());
</pre>
<p>What remains is to explain how we can set this array of content types first through a module configuration form.</p>
<p>We will implement <a href="http://api.drupal.org/api/drupal/modules--system--system.api.php/function/hook_menu/7">hook_menu</a> so we get a configuration form at our module at the relative path <em>admin/config/content/nodes_to_text_file</em>:</p>
<pre class="is_code">
/**
 * Implements hook_menu().
 */
function nodes_to_text_file_menu() {
  $items = array();  

  $items['admin/config/content/nodes_to_text_file'] = array(
    'title' =&gt; 'Nodes To Text File',
    'description' =&gt; 'Configuration for Nodes To Text File module',
    'page callback' =&gt; 'drupal_get_form',
    'page arguments' =&gt; array('nodes_to_text_file_form'),
    'access arguments' =&gt; array('access administration pages'),
    'type' =&gt; MENU_NORMAL_ITEM
  );

  return $items;
}
</pre>
<p>Using the hook_menu hook, modules register paths to define how URL requests are handled. In this case, we are setting a path that makes a configuration form available from the Drupal Configuration page:</p>
<p><a href="http://www.integratingstuff.com/wp-content/uploads/2012/01/drupal_module_menu.png"><img src="http://www.integratingstuff.com/wp-content/uploads/2012/01/drupal_module_menu-300x98.png" alt="" title="Drupal Module Menu" width="300" height="98" class="aligncenter size-medium wp-image-568" /></a></p>
<p>We passed the form already to the array of the &#8216;page arguments&#8217; property of the link, but we didnt define it yet. We are doing so now:</p>
<pre class="is_code">
/**
 * Form function, called by drupal_get_form()
 * in nodes_to_text_file_menu().
 */
function nodes_to_text_file_form($form, &#038;$form_state) {
	$queryResult = nodes_to_text_file_retrieve_content_types();

	$options = array();
	while($record = $queryResult-&gt;fetchAssoc()) {
    	$options[$record['type']] = t($record['name']);
    } 

  	$form['nodes_to_text_file_content_types'] = array(
    	'#type' =&gt; 'checkboxes',
    	'#title' =&gt; t('Content types to include'),
    	'#default_value' =&gt; variable_get('nodes_to_text_file_content_types', array()),
    	'#description' =&gt; t('The content types to include.'),
    	'#options' =&gt; $options
  	);

  return system_settings_form($form);
}
</pre>
<p>First we are creating the array of possible content types so we can use it later to generate the necessary checkboxes on the form:</p>
<pre class="is_code">
$queryResult = nodes_to_text_file_retrieve_content_types();

	$options = array();
	while($record = $queryResult-&gt;fetchAssoc()) {
    	$options[$record['type']] = t($record['name']);
    }
</pre>
<p>In Drupal, forms should be constructed using the <a href="http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html/7">Form API</a>. We are using it to construct our form:</p>
<pre class="is_code">
$form['nodes_to_text_file_content_types'] = array(
    	'#type' =&gt; 'checkboxes',
    	'#title' =&gt; t('Content types to include'),
    	'#default_value' =&gt; variable_get('nodes_to_text_file_content_types', array()),
    	'#description' =&gt; t('The content types to include.'),
    	'#options' =&gt; $options
  	);
</pre>
<p>after which we return the form. Note that the Form API is pretty straightforward. It is generally enough to consult the API page to know what types of fields are available and which properties are available and which ones are required.</p>
<h2>6. The entire module file for reference</h2>
<pre class="is_code">
&lt;?php
/**
 * Implements hook_help.
 *
 * Displays help and module information.
 *
 * @param path
 *   Which path of the site we're using to display help
 * @param arg
 *   Array that holds the current path as returned from arg() function
 */
function nodes_to_text_file_help($path, $arg) {
  switch ($path) {
    case "admin/help#nodes_to_text_file":
      return '&lt;p&gt;'.  t("A module that creates a text file containing all content of certain types of nodes whenever a node of one of these types is added, edited or deleted") .'&lt;/p&gt;';
      break;
  }
}

/**
 * Implements hook_node_delete.
 */
function nodes_to_text_file_node_delete($node){
	nodes_to_text_file_write_file($node);
}

/**
 * Implements hook_node_update.
 */
function nodes_to_text_file_node_update($node){
	nodes_to_text_file_write_file($node);
}

/**
 * Implements hook_node_insert.
 */
function nodes_to_text_file_node_insert($node){
	nodes_to_text_file_write_file($node);
}

/**
 * Custom write file function.
 *
 * Creates the text file and stores it on the server.
 */
function nodes_to_text_file_write_file($node){
	$contentTypes = variable_get('nodes_to_text_file_content_types', array());
	$nodeType = $node-&gt;type;

	$elementFound = false;
	foreach ($contentTypes as &#038;$value) {
    	if ($nodeType === $value){
    		$elementFound = true;
    		break;
    	}
	}

	if ($elementFound){
    	$queryResult = nodes_to_text_file_contents($contentTypes);

    	global $user;
    	$username = $user-&gt;name;

   	 	if (! file_prepare_directory(file_build_uri($username))){
    		drupal_mkdir(file_build_uri($username));
    	}

    	$filename = file_build_uri($username . '/content.txt');
    	$fh = fopen($filename, 'w') or die("can't open file");

   	 	while($record = $queryResult-&gt;fetchAssoc()) {
    		$stringData = $record['nid'] . ' - ' . $record['title'] . ' - ' . $record['created'];
    		fwrite($fh, $stringData."\n");
    	} 

    	fclose($fh);
	}
}

/**
 * Custom content function.
 *
 * Retrieve data from database
 *
 * @return
 *   A result set of the targeted nodes.
 */
function nodes_to_text_file_contents($contentTypes){
  //Use Database db_select API to retrieve nodes.
  global $user;
  $uid = $user-&gt;uid;

  $queryResult = db_select('node', 'n')
    -&gt;fields('n', array('nid', 'title', 'created'))
    -&gt;condition('uid', $uid) //owner is current user.
    -&gt;condition('status', 1) //Published.
    -&gt;condition('type', $contentTypes, 'in') //Node type is in $contentTypes
    -&gt;orderBy('created', 'DESC') //Most recent first.
    -&gt;execute();
  return $queryResult;
}

/**
 * Function that retrieves the content types from the database.
 *
 * Retrieve content types from database
 *
 * @return
 *   A result set of content types.
 */
function nodes_to_text_file_retrieve_content_types(){
  $queryResult = db_select('node_type', 'nt')
    -&gt;fields('nt', array('type', 'name'))
    -&gt;condition('module', 'node') //only node content types
    -&gt;orderBy('type', 'ASC')
    -&gt;execute();
  return $queryResult;
}

/**
 * Form function, called by drupal_get_form()
 * in nodes_to_text_file_menu().
 */
function nodes_to_text_file_form($form, &#038;$form_state) {
	$queryResult = nodes_to_text_file_retrieve_content_types();

	$options = array();
	while($record = $queryResult-&gt;fetchAssoc()) {
    	$options[$record['type']] = t($record['name']);
    } 

  	$form['nodes_to_text_file_content_types'] = array(
    	'#type' =&gt; 'checkboxes',
    	'#title' =&gt; t('Content types to include'),
    	'#default_value' =&gt; variable_get('nodes_to_text_file_content_types', array()),
    	'#description' =&gt; t('The content types to include.'),
    	'#options' =&gt; $options
  	);

  return system_settings_form($form);
}

/**
 * Implements hook_menu().
 */
function nodes_to_text_file_menu() {
  $items = array();  

  $items['admin/config/content/nodes_to_text_file'] = array(
    'title' =&gt; 'Nodes To Text File',
    'description' =&gt; 'Configuration for Nodes To Text File module',
    'page callback' =&gt; 'drupal_get_form',
    'page arguments' =&gt; array('nodes_to_text_file_form'),
    'access arguments' =&gt; array('access administration pages'),
    'type' =&gt; MENU_NORMAL_ITEM
  );

  return $items;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.integratingstuff.com/2012/01/23/how-to-create-a-drupal-7-module-introduction-to-drupal-modules-hooks-drupal-database-api-drupal-file-api-and-drupal-form-api/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Migrating the contents of a MySql database from a Windows/Mac server to a Linux server</title>
		<link>http://www.integratingstuff.com/2011/12/30/migrating-the-contents-of-a-mysql-database-from-a-windowsmac-server-to-a-linux-server/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=migrating-the-contents-of-a-mysql-database-from-a-windowsmac-server-to-a-linux-server</link>
		<comments>http://www.integratingstuff.com/2011/12/30/migrating-the-contents-of-a-mysql-database-from-a-windowsmac-server-to-a-linux-server/#comments</comments>
		<pubDate>Fri, 30 Dec 2011 17:21:15 +0000</pubDate>
		<dc:creator>Steffen Luypaert</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Migrating databases]]></category>
		<category><![CDATA[MySql]]></category>

		<guid isPermaLink="false">http://www.integratingstuff.com/?p=535</guid>
		<description><![CDATA[It is easy to make a backup of a MySql database and import the export again into another MySql database. However, when the backup is made on a Windows or Mac machine and is then used on a Linux machine, it is possible problems arise due to the fact that filenames/tablenames are case sensitive on the Linux OS but the export on Windows/Mac does not preserve case. <a href="http://stackoverflow.com/questions/6248735/how-to-force-mysql-to-use-case-sensitive-table-names-in-windows">Some propose other solutions – passing a parameter when starting the database or upgrading to a more recent version of MySql - to solve this problem</a>. However, because I had no control over the database to take the backup from, I had to use the below method which just takes the backup file and a text file in which all tablenames are present with their case set right, and then uses the second file to simply replace all lowercase occurences in the first file with the version with the proper case.]]></description>
			<content:encoded><![CDATA[<p>It is easy to make a backup of a MySql database and import the export again into another MySql database. However, when the backup is made on a Windows or Mac machine and is then used on a Linux machine, it is possible problems arise due to the fact that filenames/tablenames are case sensitive on the Linux OS but the export on Windows/Mac does not preserve case. <a href="http://stackoverflow.com/questions/6248735/how-to-force-mysql-to-use-case-sensitive-table-names-in-windows">Some propose other solutions – passing a parameter when starting the database or upgrading to a more recent version of MySql &#8211; to solve this problem</a>. However, because I had no control over the database to take the backup from, I had to use the below method which just takes the backup file and a text file in which all tablenames are present with their case set right, and then uses the second file to simply replace all lowercase occurences in the first file with the version with the proper case.</p>
<h2>Making a backup of a Mysql database and restoring it</h2>
<p>Making a backup of a MySql database is straightforward. I am giving the statements below for a Mac, but on Windows the same mysqldump and mysql commands can be used from the bin folder of the MySql installation.</p>
<p>First navigate to your MySql installation folder. This will probably be something like:</p>
<pre class="is_code">
cd /usr/local/mysql
</pre>
<p>And then run mysqldump:</p>
<pre class="is_code">
sudo ./bin/mysqldump -u &lt;username&gt; -p &lt;password&gt; testdatabase &gt; /development/testdatabase.sql
</pre>
<p>where &lt;username&gt; is your mysql username and &lt;password&gt; is your mysql password.</p>
<p>This will generate a sql script in the development folder that is able to recreate all tables and indexes and reinsert all data that are available in the testdatabase, by running the following command on the target server:</p>
<pre class="is_code">
sudo ./bin/mysql testdatabase &lt; /development/testdatabase.sql
</pre>
<p>assuming the testdatabase.sql was first sent to the development folder on the target server by using the <a href="http://linux.about.com/od/commands/l/blcmdl1_scp.htm">scp command</a> or some graphical client.</p>
<p>However, when running the above mysqldump command on Mac or Windows, all tablenames are stored in lowercase in the target sql script file by default. When it is then imported on a Linux server, all tablenames are in lowercase as well.</p>
<p>This is a problem, since the case of the tablenames matters on Linux machines. It is possible that applications – written in PHP, Java or something else &#8211; that will make use of the database expect some or all of these tablenames to be in upper case or have its first letter capitalized. These applications will then not run correctly.</p>
<h2>Case sensitivity: the problem when migrating a MySql database from Windows/Mac to Linux</h2>
<p>Hence, it is necessary the cases are preserved in the generated sql script. <a href="http://stackoverflow.com/questions/2992079/mysqldump-problem-with-case-sensitivity-win-linux">The answer to this Stackoverflow question</a> suggests to restart the mysql database on the Mac/windows server with the lower_case_table_names parameter set to 0. For more information about this, please check <a href="http://dev.mysql.com/doc/refman/5.1/en/identifier-case-sensitivity.html">the Mysql documentation about the lower_case_table_names parameter</a>.</p>
<p>However, you might not have the permissions to take the database offline, restart it with this parameter and then run mysqldump again. You are then stuck with the script with only lower case table names. I think the only option is then to edit the script and replace all lower case occurences with the version with the proper case.</p>
<p>The method that I describe below is just a quick way to do this using Java.</p>
<h3>Getting the list of tablenames with their case right</h3>
<p>Most applications – such as Java web applications (using JPA/Hibernate for example), and Drupal and WordPress installations &#8211; are able to automatically create the database tables they need if they are missing. Hence, you can run the application once and make sure the tables are generated. You then open a MySql terminal. </p>
<p>On the Linux machine, you would run the following from the mysql installation bin folder:</p>
<pre class="is_code">
mysql --user=&lt;user&gt; --password=&lt;password&gt;
</pre>
<p>After which you will get the mysql terminal.<br />
Assuming the tables were already generated by the web application in the testdatabase database, you run:</p>
<pre class="is_code">
mysql&gt; show tables from testdatabase;
</pre>
<p>Which in my case renders:</p>
<pre class="is_code">
+--------------------------------+
| Tables_in_testdatabase         |
+--------------------------------+
| Account_                       |
| Address                        |
| AnnouncementsDelivery          |
| AnnouncementsEntry             |
| AnnouncementsFlag              |
| AssetCategory                  |
| AssetCategoryProperty          |
| AssetEntries_AssetCategories   |
| AssetEntries_AssetTags         |
| AssetEntry                     |
| AssetLink                      |
| AssetTag                       |
| AssetTagProperty               |
| AssetTagStats                  |
| AssetVocabulary                |
| BlogsEntry                     |
| BlogsStatsUser                 |
| BookmarksEntry                 |
| BookmarksFolder                |
| BrowserTracker                 |
| CalEvent                       |
| Chat_Entry                     |
| Chat_Status                    |
| ClassName_                     |
| ClusterGroup                   |
| Company                        |
| Contact_                       |
| Counter                        |
| Country                        |
| CyrusUser                      |
| CyrusVirtual                   |
| DLFileEntry                    |
| DLFileRank                     |
| DLFileShortcut                 |
| DLFileVersion                  |
| DLFolder                       |
| EmailAddress                   |
| ExpandoColumn                  |
| ExpandoRow                     |
| ExpandoTable                   |
| ExpandoValue                   |
| Group_                         |
| Groups_Orgs                    |
| Groups_Permissions             |
| Groups_Roles                   |
| Groups_UserGroups              |
| IGFolder                       |
| IGImage                        |
| Image                          |
| JournalArticle                 |
| JournalArticleImage            |
| JournalArticleResource         |
| JournalContentSearch           |
| JournalFeed                    |
| JournalStructure               |
| JournalTemplate                |
| Layout                         |
| LayoutPrototype                |
| LayoutSet                      |
| LayoutSetPrototype             |
| ListType                       |
| Lock_                          |
| MBBan                          |
| MBCategory                     |
| MBDiscussion                   |
| MBMailingList                  |
| MBMessage                      |
| MBMessageFlag                  |
| MBStatsUser                    |
| MBThread                       |
| Mail_Account                   |
| Mail_Attachment                |
| Mail_Folder                    |
| Mail_Message                   |
| MembershipRequest              |
| OpenSocial_Gadget              |
| OrgGroupPermission             |
| OrgGroupRole                   |
| OrgLabor                       |
| Organization_                  |
| PasswordPolicy                 |
| PasswordPolicyRel              |
| PasswordTracker                |
| Permission_                    |
| Phone                          |
| PluginSetting                  |
| PollsChoice                    |
| PollsQuestion                  |
| PollsVote                      |
| Portlet                        |
| PortletItem                    |
| PortletPreferences             |
| QUARTZ_BLOB_TRIGGERS           |
| QUARTZ_CALENDARS               |
| QUARTZ_CRON_TRIGGERS           |
| QUARTZ_FIRED_TRIGGERS          |
| QUARTZ_JOB_DETAILS             |
| QUARTZ_JOB_LISTENERS           |
| QUARTZ_LOCKS                   |
| QUARTZ_PAUSED_TRIGGER_GRPS     |
| QUARTZ_SCHEDULER_STATE         |
| QUARTZ_SIMPLE_TRIGGERS         |
| QUARTZ_TRIGGERS                |
| QUARTZ_TRIGGER_LISTENERS       |
| RatingsEntry                   |
| RatingsStats                   |
| Region                         |
| Release_                       |
| ResourceAction                 |
| ResourceCode                   |
| ResourcePermission             |
| Resource_                      |
| Role_                          |
| Roles_Permissions              |
| SCFrameworkVersi_SCProductVers |
| SCFrameworkVersion             |
| SCLicense                      |
| SCLicenses_SCProductEntries    |
| SCProductEntry                 |
| SCProductScreenshot            |
| SCProductVersion               |
| SN_MeetupsEntry                |
| SN_MeetupsRegistration         |
| SN_WallEntry                   |
| ServiceComponent               |
| Shard                          |
| ShoppingCart                   |
| ShoppingCategory               |
| ShoppingCoupon                 |
| ShoppingItem                   |
| ShoppingItemField              |
| ShoppingItemPrice              |
| ShoppingOrder                  |
| ShoppingOrderItem              |
| SocialActivity                 |
| SocialEquityAssetEntry         |
| SocialEquityGroupSetting       |
| SocialEquityHistory            |
| SocialEquityLog                |
| SocialEquitySetting            |
| SocialEquityUser               |
| SocialRelation                 |
| SocialRequest                  |
| Subscription                   |
| TasksProposal                  |
| TasksReview                    |
| Team                           |
| Ticket                         |
| UserGroup                      |
| UserGroupGroupRole             |
| UserGroupRole                  |
| UserIdMapper                   |
| UserTracker                    |
| UserTrackerPath                |
| User_                          |
| Users_Groups                   |
| Users_Orgs                     |
| Users_Permissions              |
| Users_Roles                    |
| Users_Teams                    |
| Users_UserGroups               |
| Vocabulary                     |
| WSRP_WSRPConsumer              |
| WSRP_WSRPConsumerPortlet       |
| WSRP_WSRPProducer              |
| WebDAVProps                    |
| Website                        |
| WikiNode                       |
| WikiPage                       |
| WikiPageResource               |
| WorkflowDefinitionLink         |
| WorkflowInstanceLink           |
| blocked_user                   |
| deleted_message                |
| private_message                |
| read_message                   |
+--------------------------------+
176 rows in set (0.55 sec)
</pre>
<p>The above is a list of tablenames for the Liferay 6.0 portal and migrating these tables is a case in which I actually used the method described here. I stripped the list of all pipes(|) and saved the list of tablenames into a txt file, one tablename per line.</p>
<p>If you cannot generate the list of tablenames with the right case automatically like above, you will need to manually create this file, severely slowing up the method used in this tutorial.</p>
<h3>Setting the case right with some Java code</h3>
<p>The below Java class takes the testdatabase.sql file and the tablenames.txt file as input and writes the sql script with the cases set right to a testdatabase-converted.sql file:</p>
<pre class="is_code">
public class SetCaseRight {

	private static List&lt;String&gt; readFile(String fileName){
		try{
			List&lt;String&gt; lines = new ArrayList&lt;String&gt;();
			FileInputStream fstream = new FileInputStream(fileName);
			DataInputStream in = new DataInputStream(fstream);
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			String strLine;
			while ((strLine = br.readLine()) != null)   {
				lines.add(strLine);
			}
			in.close();
			return lines;
		}catch (Exception e){
			e.printStackTrace();
			return null;
		}
	}

	private static String readFileAsString(String fileName){
        try {
			StringBuffer fileData = new StringBuffer(1000);
			BufferedReader reader = new BufferedReader(new FileReader(fileName));
			char[] buf = new char[1024];
			int numRead=0;
			while((numRead=reader.read(buf)) != -1){
			    String readData = String.valueOf(buf, 0, numRead);
			    fileData.append(readData);
			    buf = new char[1024];
			}
			reader.close();
			return fileData.toString();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
    }

	private static void writeStringToFile(String s, String fileName){
		try {
			BufferedWriter out = new BufferedWriter(new FileWriter(fileName));
			out.write(s);
			out.close();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args){
		String sqlSourceFile;
		String tableNamesTxtFile;
		String sqlTargetFile;
		if (args.length &gt;= 1){ sqlSourceFile = args[0];} else { sqlSourceFile = "testdatabase.sql";}
		if (args.length &gt;= 2){ tableNamesTxtFile = args[1];} else { tableNamesTxtFile = "tablenames.txt";}
		if (args.length &gt;= 3){ sqlTargetFile = args[2];} else { sqlTargetFile = "testdatabase-converted.sql";}
		String sql = getSql(sqlSourceFile);
		for (String tableName: readTableNames(tableNamesTxtFile)){
			sql = sql.replaceAll("`(?i)" + tableName.trim()+"`", "`"+tableName.trim()+"`");
		}
		writeStringToFile(sql, sqlTargetFile);
	}

	public static String getSql(String sqlSourceFile){
		return readFileAsString(sqlSourceFile);
	}

	public static List&lt;String&gt; readTableNames(String tableNamesTxtFile){
		return readFile(tableNamesTxtFile);
	}
}
</pre>
<p>It is also possible to run the above class command line – without having to compile it yourself &#8211; <a href="http://www.integratingstuff.com/wp-content/uploads/2012/01/SetCaseRight.class">by using this SetCaseRight class file</a>:</p>
<pre class="is_code">
java SetCaseRight testdatabase.sql tablenames.txt testdatabase-converted.sql
</pre>
<p>in a folder where java is on the PATH and where the first argument is the sqlTargetFile, the second argument is the tableNamesTxtFile and the third argument is the sqlTargetFile.</p>
<p>The resulting sql file is then ready to be imported on the Linux server.</p>
<div class="is_note">
Note: The above class is not perfect. It is possible it replaces too many parts of the sql file, such as columnnames that are matching one of the tablenames present in the text file. This should not cause a problem, since column names are case insensitive as far as I know, but if it is a problem, you will need to modify the above Java class and make the string replacement a bit smarter.
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.integratingstuff.com/2011/12/30/migrating-the-contents-of-a-mysql-database-from-a-windowsmac-server-to-a-linux-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Styling Liferay: creating a Liferay Theme</title>
		<link>http://www.integratingstuff.com/2011/11/30/styling-liferay-creating-a-liferay-theme/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=styling-liferay-creating-a-liferay-theme</link>
		<comments>http://www.integratingstuff.com/2011/11/30/styling-liferay-creating-a-liferay-theme/#comments</comments>
		<pubDate>Wed, 30 Nov 2011 18:16:28 +0000</pubDate>
		<dc:creator>Steffen Luypaert</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Liferay]]></category>
		<category><![CDATA[Portals]]></category>

		<guid isPermaLink="false">http://www.integratingstuff.com/?p=501</guid>
		<description><![CDATA[In most Liferay projects, a custom Liferay theme needs to be developed and this article explains to developers how to do this.
Note that the <a href="http://www.liferay.com/documentation/liferay-portal/6.0/development/-/ai/creating-liferay-them-5">Liferay documentation already has some nice pages on creating Liferay themes</a>, but we are taking a more hands on approach.]]></description>
			<content:encoded><![CDATA[<p>In most Liferay projects, a custom Liferay theme needs to be developed and this article explains to developers how to do this.<br />
Note that the <a href="http://www.liferay.com/documentation/liferay-portal/6.0/development/-/ai/creating-liferay-them-5">Liferay documentation already has some nice pages on creating Liferay themes</a>, but we are taking a more hands on approach.</p>
<h2>Setting up the theme project</h2>
<p>We are assuming you will be using Eclipse, but will always tell what is going on under the hood, so other IDE(or commandline!) guys should also be able to follow.</p>
<p>You should start out by downloading the Liferay Plugins SDK from the bottom of <a href="http://www.liferay.com/downloads/liferay-portal/additional-files">the Liferay additional files page</a>.<br />
Eclipse users should also install the Liferay IDE Eclipse Plugin and add a Liferay Server(and runtime) after. More info on how to do this can be found in <a href="http://www.liferay.com/community/wiki/-/wiki/Main/Liferay+IDE+Getting+Started+Tutorial">the Liferay documentation on installing the Liferay IDE</a> or at this very own blog, in the last part of <a href="http://www.integratingstuff.com/2011/05/29/getting-started-with-portals-writing-a-portlet-with-spring-portlet-mvc-and-deploying-it-to-a-portal/">the getting started with portals and Spring Portlet MVC post</a>.</p>
<p>If you were already working with Liferay, you probably had these installed already anyway and the only thing you need to do then, is start your Liferay server.</p>
<p>Then, within Eclipse, choose New&gt;Project&gt;Liferay&gt;Liferay Project and then check Theme in the box.</p>
<p><a href="http://www.integratingstuff.com/wp-content/uploads/2011/11/create-liferay-theme.png"><img src="http://www.integratingstuff.com/wp-content/uploads/2011/11/create-liferay-theme.png" alt="Creating a Liferay Theme project in Eclipse" title="Creating a Liferay Theme project in Eclipse" width="586" height="657" class="alignnone size-full wp-image-504" /></a></p>
<p>What the theme plugin does is run a script from the &lt;liferay-sdk-home&gt;/themes folder that generates a Liferay theme project for you, in your Eclipse workspace.<br />
You can run the script manually by entering </p>
<pre class="is_code">
./create.sh integrating-stuff "Integrating Stuff"
</pre>
<p>or </p>
<pre class="is_code">
create.bat integrating-stuff "Integrating Stuff"
</pre>
<p>in a terminal from the said &lt;sdkhome&gt;/themes folder.</p>
<p>The Liferay IDE also takes a look at your Liferay runtime and copies a bunch of files to the docroot folder of your project. </p>
<div class="is_note">
Note: That is, if you have the &#8220;Build automatically&#8221; feature on in Eclipse. The copying of these files is done by the Ant build script included in the project and this script is ran automatically when the project gets built.
</div>
<p>These files represent the _styled theme, a very basic Liferay theme, which can be found in the portal source in the portal-web/docroot/html/themes folder or in the docroot/html/themes folder of your Liferay install.<br />
<a href="http://www.liferay.com/documentation/liferay-portal/6.0/development/-/ai/theme-inheritance">As the Liferay documentation indicates</a>, almost all themes will use the “_styled” theme as a base. If you want to start from scratch, the parent of your theme would be the “_unstyled” theme. Inheriting from “_unstyled” would give you quite a bit more work but would give you full control of the theme.</p>
<div class="is_note">
Note: _styled and _unstyled are very basic, abstract parent themes. They are not production ready. The default Liferay theme &#8211; “Classic” &#8211; inherits from _styled and is the official example of a production ready theme.
</div>
<p>Any of the files that were copied to your docroot folder can be overridden by your theme by placing them in your _diffs folder. In other words, the _diffs folder will contain all files that differ from your parent theme.</p>
<p>Note that, as already indicated above, the “_styled” theme is not production ready. Since our _diffs folder is still empty, our theme – which is currently not overriding anything and is an exact representation of the “_styled” theme &#8211; would not look that great if we would deploy it to Liferay right now.<br />
Therefore, it is a better idea to copy the content of the  _diffs folder of the production ready theme you want to start from into your own theme&#8217;s _diffs folder. To start from the default “Classic” Liferay theme, download the portal source(link) and copy the _diffs folder from the Classic theme at portal-web/docroot/html/themes to your own theme&#8217;s _diffs folder.<br />
Now your theme is production ready and ready for deployment.</p>
<h2>2. Deploying the theme to Liferay</h2>
<p>You probably already noticed the ant build script in the root of your project. If you run the default ant goal “deploy” of this script, the theme is published to your Liferay server.<br />
(If you are not doing this from within Eclipse, you need to properly set the values in the build.properties file in the ssdk&#8217;s theme folder.)</p>
<p>Let&#8217;s deploy and enable our theme on our Liferay server, which for now, looks exactly the same as the default “Classic” theme. If the theme deployed successfully, the Liferay logging should contain something like:</p>
<p><a href="http://www.integratingstuff.com/wp-content/uploads/2011/11/theme_deploy_logging.png"><img src="http://www.integratingstuff.com/wp-content/uploads/2011/11/theme_deploy_logging.png" alt="Liferay Theme being deployed - logging" title="Liferay Theme being deployed - logging" width="484" height="30" class="aligncenter size-full wp-image-506" /></a></p>
<div class="is_note">
Note: To set the theme on a page on Liferay and test it, go to Manage&gt;Page&gt;Look and Feel, and select our new theme there. Note that the theme description is lacking a thumbnail. If you want to add one, take a screenshot of a Liferay page with your theme applied, name it thumbnail.png, scale it down to 150 pixels wide and 120 pixels high and put in in the _diffs/images folder folder, as described in <a href="http://www.liferay.com/documentation/liferay-portal/6.0/development/-/ai/thumbnails">the Liferay documentation on theme thumbnails</a>.
</div>
<h2>3. Overriding parts of the parent theme</h2>
<p>The content of the_diffs folder we copied from the Classic theme consisted of 3 folders: css, images and js(javascript). In the _styled theme there is one additional folder, templates, of which the classic theme does not override anything. This is recommended practice: themes should try to avoid overriding template files since they are likely to change in between Liferay versions so changing them might make porting the theme to a new Liferay version more difficult.</p>
<h3>a. overriding css</h3>
<p>Now, to add a nice gradient background image and change the default text size and font, we have to modify our custom.css file.</p>
<p>We will change the</p>
<pre class="is_code">
body {
	background: #EEF0F2;
	font-size: 11px;
}
</pre>
<p>into:</p>
<pre class="is_code">
body {
        background-color: #4F555B;
	background-image: url("../images/layout/bg-grad.gif");
	background-repeat: repeat-x;
	color: #FFFFFF;
	font-family: Verdana,Helvetica,sans-serif;
	font-size: 11px;
}
</pre>
<p>and also create a layout_folder in our images folder and add the file <a href="http://www.integratingstuff.com/wp-content/uploads/2011/11/bg-grad.gif">bg-grad.gif</a> to it. </p>
<p>If we redeploy the theme and load our Liferay page, we see that the background has changed and text appears a bit different. Pretty easy, huh.</p>
<p><a href="http://www.integratingstuff.com/wp-content/uploads/2011/11/liferay_background_changed.png"><img src="http://www.integratingstuff.com/wp-content/uploads/2011/11/liferay_background_changed.png" alt="Liferay background changed with new theme" title="Liferay background changed with new theme" width="596" height="339" class="alignnone size-full wp-image-511" /></a></p>
<div class="is_note">
Note: I also replaced the Liferay logo with the Integrating Stuff logo by navigating to Manage&gt;Settings&gt;Logo and uploading the logo file there.
</div>
<h3>b. Overriding and adding images</h3>
<p>In the previous section, we already added a background image to the theme. If you want to override an image, you just need to add it to the images folder as well, but the image needs to have the same folder structure and file name as the one you want to override.<br />
For example, if you want to override some emoticons, you would create an emoticons folder(you need to look at the _styled theme files to know what you can override) and start putting names there of files that also exist in the parent theme(angry.gif, blank.gif,..).</p>
<h3>c. Overriding the custom javascript</h3>
<p>This can be done the same way images are overridden. However, the _styled theme only has one javascript file: main.js, which, with Liferay 6, only contains some logic that keeps the Liferay breadcrumbs always on screen.</p>
<h3>d. Overriding the template files</h3>
<p>As mentioned already, the Liferay documentation advises to avoid overriding the template files. That being said, almost all projects I know off involved creating themes that were modifying these templates.<br />
If one wants to add or remove parts of the page and the modifications go beyond styling dom elements, these templates are usually changed. The view technology these files use is <a href="http://en.wikipedia.org/wiki/Apache_Velocity">Velocity</a>.</p>
<p>The two most important ones are portal-normal.vm – which renders the whole page &#8211; and portlet.vm – which renders one portlet. The other ones respectively define additional velocity variables(init_custom.vm), render the navigation bar(navigation.vm) and render the popup pages(portal_pop_up.vm).</p>
<p>Let&#8217;s take a look at the portal-normal.vm Velocity template:</p>
<pre class="is_code">
&lt;!DOCTYPE html&gt;

#parse ($init)

&lt;html class="#language("lang.dir")" dir="#language("lang.dir")" lang="$w3c_language_id"&gt;

&lt;head&gt;
	&lt;title&gt;$the_title - $company_name&lt;/title&gt;

	$theme.include($top_head_include)
&lt;/head&gt;

&lt;body class="$css_class"&gt;

#if($is_signed_in)
	#dockbar()
#end

&lt;div id="wrapper"&gt;
	&lt;a href="#main-content" id="skip-to-content"&gt;#language("skip-to-content")&lt;/a&gt;

	&lt;header id="banner" role="banner"&gt;
		&lt;hgroup id="heading"&gt;
			&lt;h1 class="company-title"&gt;
				&lt;a class="logo" href="$company_url" title="#language("go-to") $company_name"&gt;
					&lt;span&gt;$company_name&lt;/span&gt;
				&lt;/a&gt;
			&lt;/h1&gt;

			&lt;h2 class="community-title"&gt;
				&lt;a href="$community_default_url" title="#language("go-to") $community_name"&gt;
					&lt;span&gt;$community_name&lt;/span&gt;
				&lt;/a&gt;
			&lt;/h2&gt;

			&lt;h3 class="page-title"&gt;
				&lt;span&gt;$the_title&lt;/span&gt;
			&lt;/h3&gt;
		&lt;/hgroup&gt;

		#if(!$is_signed_in)
			&lt;a href="$sign_in_url" id="sign-in" rel="nofollow"&gt;$sign_in_text&lt;/a&gt;
		#end

		#if ($update_available_url)
			&lt;div class="popup-alert-notice"&gt;
				&lt;a class="update-available" href="$update_available_url"&gt;#language("updates-are-available-for-liferay")&lt;/a&gt;
			&lt;/div&gt;
		#end

		#if ($has_navigation)
			#parse ("$full_templates_path/navigation.vm")
		#end
	&lt;/header&gt;

	&lt;div id="content"&gt;
		&lt;nav class="site-breadcrumbs" id="breadcrumbs"&gt;
			&lt;h1&gt;
				&lt;span&gt;#language("breadcrumbs")&lt;/span&gt;
			&lt;/h1&gt;

			#breadcrumbs()
		&lt;/nav&gt;

		#if ($selectable)
			$theme.include($content_include)
		#else
			$portletDisplay.recycle()

			$portletDisplay.setTitle($the_title)

			$theme.wrapPortlet("portlet.vm", $content_include)
		#end
	&lt;/div&gt;

	&lt;footer id="footer" role="contentinfo"&gt;
		&lt;p class="powered-by"&gt;
			#language("powered-by") &lt;a href="http://www.liferay.com" rel="external"&gt;Liferay&lt;/a&gt;
		&lt;/p&gt;
	&lt;/footer&gt;
&lt;/div&gt;

&lt;/body&gt;

$theme.include($bottom_include)

&lt;/html&gt;
</pre>
<p>If one would want (and is allowed to) remove the “Powered by Liferay” line, he can easily do this by just removing the line containing the text.</p>
<p>If the static htmldesign/prototypes are already made by web designers, it is easy for developers to port this created design to Liferay by copying the html to the portal-normal.vm file and inserting the Velocity directives where required.<br />
All these Velocity templates are clearly readable. When taking a look at the above file, it is obvious how to replace the whole Liferay header, for example.</p>
<h3>4. More advanced stuff</h3>
<p>There is more advanced stuff one can use to fine tune a theme and is not covered by this tutorial – such as <a href="http://www.liferay.com/documentation/liferay-portal/6.0/development/-/ai/settings">adding settings</a> or <a href="http://www.liferay.com/documentation/liferay-portal/6.0/development/-/ai/color-schemes">color schemes</a> to a theme. Although this tutorial gets you started from a practical point of view, it is probably a good idea to scan through <a href="http://www.liferay.com/documentation/liferay-portal/6.0/development/-/ai/creating-liferay-them-5">the Liferay documentation on themes</a> as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.integratingstuff.com/2011/11/30/styling-liferay-creating-a-liferay-theme/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Adding a webserver to an Android app</title>
		<link>http://www.integratingstuff.com/2011/10/24/adding-a-webserver-to-an-android-app/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=adding-a-webserver-to-an-android-app</link>
		<comments>http://www.integratingstuff.com/2011/10/24/adding-a-webserver-to-an-android-app/#comments</comments>
		<pubDate>Mon, 24 Oct 2011 04:10:34 +0000</pubDate>
		<dc:creator>Steffen Luypaert</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[http protocol]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.integratingstuff.com/?p=474</guid>
		<description><![CDATA[In this article, I give some example code on how to implement a webserver in an Android app, a functionality that can be handy if you want to give your app a web interface that can be accessed from a laptop or computer, which could be useful to enable quicker data entry amongst other things.
I also show some example code on how to parse a multipart message, in case you want the client to be able to sent form data/upload files to the webserver.]]></description>
			<content:encoded><![CDATA[<p>In this article, I give some example code on how to implement a webserver in an Android app, a functionality that can be handy if you want to give your app a web interface that can be accessed from a laptop or computer, which could be useful to enable quicker data entry amongst other things.<br />
I also show some example code on how to parse a multipart message, in case you want the client to be able to sent form data/upload files to the webserver.</p>
<h1>WebServer class</h1>
<p>Everything that we are going to use is already present in the Android API. We are not going to need any additional libs.</p>
<p>A pragmatic implementation looks like this:</p>
<pre class="is_code">
package com.integratingstuff.android.webserver;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;

import org.apache.http.HttpException;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.DefaultHttpResponseFactory;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.HttpRequestHandlerRegistry;
import org.apache.http.protocol.HttpService;
import org.apache.http.protocol.ResponseConnControl;
import org.apache.http.protocol.ResponseContent;
import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer;

import android.content.Context;

public class WebServer {

	public static boolean RUNNING = false;
	public static int serverPort = 8080;

	private static final String ALL_PATTERN = "*";
	private static final String EXCEL_PATTERN = "/*.xls";
	private static final String HOME_PATTERN = "/home.html";

	private Context context = null;

	private BasicHttpProcessor httpproc = null;
	private BasicHttpContext httpContext = null;
	private HttpService httpService = null;
	private HttpRequestHandlerRegistry registry = null;

	public WebServer(Context context) {
		this.setContext(context);

		httpproc = new BasicHttpProcessor();
		httpContext = new BasicHttpContext();

		httpproc.addInterceptor(new ResponseDate());
		httpproc.addInterceptor(new ResponseServer());
		httpproc.addInterceptor(new ResponseContent());
		httpproc.addInterceptor(new ResponseConnControl());

		httpService = new HttpService(httpproc,
		    new DefaultConnectionReuseStrategy(), new DefaultHttpResponseFactory());

		registry = new HttpRequestHandlerRegistry();

		//registry.register(HOME_PATTERN, new HomeCommandHandler(context));

		httpService.setHandlerResolver(registry);
	}

	private ServerSocket serverSocket;

	public void runServer() {
		try {
			serverSocket = new ServerSocket(serverPort);

			serverSocket.setReuseAddress(true);

			while (RUNNING) {
				try {
					final Socket socket = serverSocket.accept();

					DefaultHttpServerConnection serverConnection = new DefaultHttpServerConnection();

					serverConnection.bind(socket, new BasicHttpParams());

					httpService.handleRequest(serverConnection, httpContext);

					serverConnection.shutdown();
				} catch (IOException e) {
					e.printStackTrace();
				} catch (HttpException e) {
					e.printStackTrace();
				}
			}

			serverSocket.close();
		} catch (SocketException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		RUNNING = false;
	}

	public synchronized void startServer() {
		RUNNING = true;
		runServer();
	}

	public synchronized void stopServer() {
		RUNNING = false;
		if (serverSocket != null) {
			try {
				serverSocket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public void setContext(Context context) {
		this.context = context;
	}

	public Context getContext() {
		return context;
	}
}
</pre>
<p>In the WebServer contructor we are initializing an HttpService. We are using all the default implementations here. The interesting part is the construction of the HttpRequestHandlerRegistry. As we will see, we will add a custom requesthandler to this registry which shall build the response for a particular request.</p>
<p>In the runServer method we actually start the server by initiating a low level ServerSocket and make it accept connections. We then continiously bind the socket to our webserver implementation and tell it to handle the request. </p>
<p>The startServer and stopServer methods are the methods actually used to start and stop the server.</p>
<p>In Android apps, a server like this should be run as an Android <a href="http://developer.android.com/reference/android/app/Service.html">Service</a>. So, we are implementing the following WebServerService:</p>
<pre class="is_code">
package com.integratingstuff.android.webserver;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class WebServerService extends Service {

	private WebServer server = null;

	@Override
	public void onCreate() {
		Log.i("HTTPSERVICE", "Creating and starting httpService");
		super.onCreate();
		server = new WebServer(this);
		server.startServer();
	}

	@Override
	public void onDestroy() {
		Log.i("HTTPSERVICE", "Destroying httpService");
		server.stopServer();
		super.onDestroy();
	}

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}
}
</pre>
<p>Which we can start from the Android application like this:</p>
<pre style="is_code">
Intent webServerService = new Intent(context, WebServerService.class);
context.startService(webServerService);
</pre>
<h1>HttpRequestHandler</h1>
<p>Our WebServer is now running, but we did not register any requesthandlers yet. In our webserver, we commented the following line:</p>
<pre class="is_code">
registry.register(HOME_PATTERN, new HomeCommandHandler(context));
</pre>
<p>Let&#8217;s uncomment it and implement the HomeCommandHandler:</p>
<pre class="is_code">
package com.integratingstuff.android.webserver;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.entity.ContentProducer;
import org.apache.http.entity.EntityTemplate;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;

import android.content.Context;

public class HomeCommandHandler implements HttpRequestHandler {
	private Context context = null;

	public HomeCommandHandler(Context context) {
		this.context = context;
	}

	@Override
	public void handle(HttpRequest request, HttpResponse response,
	    HttpContext httpContext) throws HttpException, IOException {
		HttpEntity entity = new EntityTemplate(new ContentProducer() {
			public void writeTo(final OutputStream outstream) throws IOException {
				OutputStreamWriter writer = new OutputStreamWriter(outstream, "UTF-8");
				String resp = "&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;h1&gt;Home&lt;h1&gt;&lt;p&gt;This is the homepage.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;";

				writer.write(resp);
				writer.flush();
			}
		});
		response.setHeader("Content-Type", "text/html");
		response.setEntity(entity);
	}

	public Context getContext() {
		return context;
	}
}
</pre>
<p>We are mapping the pattern home.html to this requesthandler. This handler will send some basic html back as its response. </p>
<p>If you now surf to http://&lt;ip-of-device&gt;:8080/home.html, you should see the homepage with the &#8220;This is the homepage&#8221; message.</p>
<p>So now, our webserver is up and running and responding to home.html requests. You can easily add more requesthandlers to the registry, that match specific patterns or wildcard * patterns.</p>
<h1>MultipartParser</h1>
<p>The above can be easily found elsewhere, so to give this article some added value, I will quickly indicate below how to parse form date/get the contents of files contained in the request.</p>
<h3>Code</h3>
<p>We will need to parse a multipart request manually. I am just going to give the code snippets and I am not going into the parsing intrinsics, but basically, the http protocol defines boundary delimiters for multipart messages. What we are doing with the following MultipartParser is read the entire sent form into a Multivalued map(a map of which the value is a list of a certain type of object, so every key is mapped to a list of 1 or more values). Note that the MultipartParser actually uses a CaseInsensitiveMultivaluedMap that wraps a regular MultivaluedMap, because keys like &#8220;name&#8221; and &#8220;NAME&#8221; map to the same formproperty.</p>
<h4>MultipartParser</h4>
<pre class="is_code">
package com.integratingstuff.android.webserver;

import java.io.IOException;
import java.io.InputStream;

public class MultipartParser {

	public final static String SEP = "\n";

	private InputStream is;
	private byte[] boundaryBA;
	static private byte[] boundaryDelimiterBA = "--".getBytes();

	private MultivaluedMap<String, String> partHeaders;
	private PartInputStream partIS;

	private static int BOUNDARY_TYPE_START = 0;
	private static int BOUNDARY_TYPE_END = 1;
	// private static int BOUNDARY_TYPE_INVALID = 2;

	private byte[] buff;
	// the next byte to return
	private int buffIdx = 0;
	// The number of bytes that were set on the buffer (red from is);
	private int buffSize = 0;
	// the position of the next boundary ("--boundary"), -1 if does not exist in
	// this buffer
	private int boundryIdx = -1;
	// The index of the byte that is suspected of been the boundary
	private int saveIdx = 0;

	// This is a temp array that is used to read stuff into it.
	private byte[] temp = new byte[1024];

	public MultipartParser(InputStream is, String boundary) {
		this.is = is;
		boundaryBA = ("--" + boundary).getBytes();
		// make sure to allocate a buffer that is at least double then the
		// boundary length
		int buffLength = Math.max(8192, boundaryBA.length * 2);
		buff = new byte[buffLength];

	}

	private void shiftBuff() {
		System.arraycopy(buff, buffIdx, buff, 0, buffSize - buffIdx);

		buffSize -= buffIdx;
		saveIdx -= buffIdx;
		if (saveIdx < 0)
			saveIdx = 0;
		/*
		 * throw new RuntimeException("This should never happend, we found a bug.");
		 */
		boundryIdx = Math.max(-1, boundryIdx - buffIdx);
		buffIdx = 0;

		// for debug purposes
		// Arrays.fill(buff, buffIdx, buff.length-1, (byte)0);

	}

	public boolean nextPart() throws IOException {
		// if this is the first next just get rid of the PREAMBLE
		if (partIS == null) {
			partIS = new PartInputStream();
		}
		// clear the part/preamble bytes that were not read
		digestPartStream();
		if (digestBoundary() == BOUNDARY_TYPE_END)
			return false;
		partIS.setState(PartInputStream.STATE_NOT_ACTIVE);
		partIS = new PartInputStream();
		partHeaders = parseHeaders();
		return partHeaders != null;
	}

	public InputStream getPartBodyStream() {
		return partIS;
	}

	public MultivaluedMap<String, String> getPartHeaders() {
		return partHeaders;
	}

	// read till end of stream (next boundary)
	private void digestPartStream() throws IOException {
		while (partIS.read(temp) != -1) {
		}
	}

	private boolean compareByte(byte[] a, int aOffset, byte[] b, int bOffset,
	    int length) {
		for (int i = 0; i < length; i++) {
			if (a[aOffset + i] != b[bOffset + i])
				return false;
		}
		return true;
	}

	private int digestBoundary() throws IOException {
		// it might be that there is a new line before the boundary
		digestNewLine();

		// promote pointers to the end of the boundary
		buffIdx += boundaryBA.length;
		saveIdx += boundaryBA.length; // DO NOT DELETE

		// check if this is an end boundary
		int unredBytes = verifyByteReadyForRead(2);
		if (unredBytes >= 2) {
			if (compareByte(buff, buffIdx, boundaryDelimiterBA, 0,
			    boundaryDelimiterBA.length))
				return BOUNDARY_TYPE_END;
		}
		// OK
		digestNewLine();
		boundryIdx = -1;
		findBounderyIfNeeded();
		return BOUNDARY_TYPE_START;
	}

	private void findBounderyIfNeeded() {
		if (boundryIdx == -1) {
			boundryIdx = indexOf(buff, saveIdx, buffSize, boundaryBA);
			if (boundryIdx != -1) {
				int nlSize = 0;
				if (boundryIdx > 1) {
					if (buff[boundryIdx - 2] == '\r' &#038;&#038; buff[boundryIdx - 1] == '\n')
						nlSize = 2;
					else
						nlSize = 1;
				}
				if (boundryIdx == 1) {
					nlSize = 1;
				}

				saveIdx = boundryIdx - nlSize;
			} else {
				// the boundary was not found, but we can promote the save till
				// boundary size + NL size
				saveIdx = Math.max(saveIdx, buffSize - (boundaryBA.length + 2));
			}
		}
	}

	private int verifyByteReadyForRead(int required) throws IOException {
		int unreadBytes = buffSize - buffIdx - 1;
		if (unreadBytes < required) {
			fetch(required - unreadBytes);
			unreadBytes = buffSize - buffIdx;
		}
		return unreadBytes;
	}

	private int fetch(int minmum) throws IOException {
		int res = 0;
		int max2featch = buff.length - buffSize;

		if (max2featch < minmum) {
			shiftBuff();
			max2featch = buff.length - buffSize;
		}

		while (res < minmum &#038;&#038; max2featch > 0) {
			max2featch = buff.length - buffSize;

			int read = is.read(buff, buffSize, max2featch);
			if (read == -1) {
				if (res == 0)
					return -1;
				else
					break;
			}
			res += read;
			buffSize += read;
		}
		findBounderyIfNeeded();
		return res;

	}

	private void digestNewLine() throws IOException {
		// make sure we have enough byte to read
		int unreadBytes = verifyByteReadyForRead(2);
		int size = 0;

		if (unreadBytes >= 2 &#038;&#038; buff[buffIdx] == '\r' &#038;&#038; buff[buffIdx + 1] == '\n')
			size = 2;
		else if (buff[buffIdx] == '\r')
			size = 1;
		else if (buff[buffIdx] == '\n')
			size = 1;
		buffIdx += size;
		if (saveIdx < buffIdx)
			saveIdx = buffIdx;
	}

	private int indexOf(byte[] ba, int start, int end, byte[] what) {
		for (int i = start; i < end - what.length + 1; i++) {
			// only if the first byte equals do the compare (to improve
			// performance)
			if (ba[i] == what[0])
				if (compareByte(ba, i, what, 0, what.length))
					return i;
		}
		return -1;
	}

	private MultivaluedMap<String, String> parseHeaders() throws IOException {

		MultivaluedMap<String, String> headers = new CaseInsensitiveMultivaluedMap<String>();

		String line;
		do {
			line = readLine();
			if (line == null || line.equals(""))
				break;
			int semIdx = line.indexOf(":");
			headers.add(line.substring(0, semIdx).trim(), line.substring(semIdx + 1)
			    .trim());

		} while (true);
		if (saveIdx < buffIdx)
			saveIdx = buffIdx;
		return headers;
	}

	private String readLine() throws IOException {

		int lineIdx = 0;
		int breakeSize = 0;
		while (lineIdx <= verifyByteReadyForRead(lineIdx)) {
			if (buff[buffIdx + lineIdx] == '\n') {
				breakeSize = 1;
				break;
			}
			if (buff[buffIdx + lineIdx] == '\r') {
				if ((verifyByteReadyForRead(lineIdx + 1) >= lineIdx + 1)
				    &#038;&#038; (buff[buffIdx + lineIdx + 1] == '\n')) {
					breakeSize = 2;
					break;
				} else {
					breakeSize = 1;
					break;
				}
			}
			lineIdx++;
		}

		// got to the end of input without NL
		if (lineIdx == 0) {
			buffIdx += breakeSize;
			return null;
		}

		String hdr = new String(buff, buffIdx, lineIdx);
		buffIdx += lineIdx + breakeSize;
		return hdr;
	}

	public class PartInputStream extends InputStream {
		// The state of the part Stream
		// 0 active
		// 1 not active (the Parser already moved to the next part.)
		private int state = 0;
		public final static int STATE_ACTIVE = 0;
		public final static int STATE_NOT_ACTIVE = 1;

		public void setState(int status) {
			this.state = status;

		}

		@Override
		public int read(byte[] b, int off, int len) throws IOException {
			if (state == STATE_NOT_ACTIVE) {
				throw new IOException(
				    "Stream allready closed: the PartInputStream is not accesable after moving to the next part");
			}
			int available = verifyNumOfByteToReadB4Boundary(len);
			if (available < 1) {
				return available
                        }
			int size2copy = Math.min(len, available);
			System.arraycopy(buff, buffIdx, b, off, size2copy);
			buffIdx += size2copy;
			return size2copy;
		}

		@Override
		public int read() throws IOException {
			if (state == STATE_NOT_ACTIVE) {
				throw new IOException(
				    "Stream allready closed: the PartInputStream is not accesable after moving to the next part");
			}
			int i = verifyNumOfByteToReadB4Boundary(1);
			if (i < 1)
				return -1;
			// make sure that the return value is 0 - 255
			int res = buff[buffIdx] &#038; 0xff;
			if (res < 0) {
				int t = 0;
				t++;
			}
			buffIdx++;
			return res;

		}

		private int verifyNumOfByteToReadB4Boundary(int minmum) throws IOException {
			int availabe = saveIdx - buffIdx;
			if (availabe >= minmum)
				return availabe;
			//
			if (saveIdx <= boundryIdx) {
				if (availabe == 0)
					return -1;
				return availabe;
			}
			int fetched = fetch(minmum - availabe);
			availabe = saveIdx - buffIdx;
			if (availabe == 0 &#038;&#038; fetched == -1)
				return -1;

			return availabe;

		}

		@Override
		public int available() {
			return saveIdx - buffIdx;
		}
	}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.integratingstuff.com/2011/10/24/adding-a-webserver-to-an-android-app/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
