<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title type="text" xml:lang="en">Andrej Koelewijn</title>
    <link type="application/atom+xml" href="http://www.andrejkoelewijn.com/blog/atom.xml" rel="self"/>
    <link type="text/html" href="http://www.andrejkoelewijn.com/blog/" rel="alternate"/>
    <updated>2014-01-16T10:28:14+01:00</updated>
    <id>http://www.andrejkoelewijn.com/</id>
    <author>
        <name>Andrej Koelewijn</name>
        <email>andrej@koelewijn.net</email>
    </author>
    
    <entry>
        <title>Howto debug Mendix java actions</title>
        <link href="http://www.andrejkoelewijn.com/blog/2014/01/16/howto-debug-mx-java-actions/" type="text/html" rel="alternate"/>
        <published>2014-01-16T00:00:00+01:00</published>
        <updated>2014-01-16T00:00:00+01:00</updated>
        <id>http://www.andrejkoelewijn.com/blog/2014/01/16/howto-debug-mx-java-actions</id>
        <author>
          <name>Andrej Koelewijn</name>
          <uri>http://www.andrejkoelewijn.com/</uri>
        </author>
        <content type="html">&lt;p&gt;To debug Java Actions used in a Mendix Microflow you need to make some configuration changes to the way you start the Mendix runtime.&lt;/p&gt;

&lt;p&gt;Add the following in your &lt;em&gt;project settings&lt;/em&gt;, in &lt;em&gt;server configuration&lt;/em&gt; add the following to &lt;em&gt;Extra JVM parameters&lt;/em&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2014/01/mx-java-debug/java-debug-mx.png&quot; alt=&quot;Mendix Project Settings&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Start your application in Mendix.&lt;/p&gt;

&lt;p&gt;In your Java IDE you need to configure remote debugging. The following screenshot shows my configuration in IntelliJ&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2014/01/mx-java-debug/intellij_rundebug_configurations.png&quot; alt=&quot;Mendix Intellij remote debugging&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Start the debugger, put some breakpoints in your java code, and start debugging.&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <title>Profiling Mendix using JProfiler</title>
        <link href="http://www.andrejkoelewijn.com/blog/2014/01/15/profiling-mendix-using-jprofiler/" type="text/html" rel="alternate"/>
        <published>2014-01-15T00:00:00+01:00</published>
        <updated>2014-01-15T00:00:00+01:00</updated>
        <id>http://www.andrejkoelewijn.com/blog/2014/01/15/profiling-mendix-using-jprofiler</id>
        <author>
          <name>Andrej Koelewijn</name>
          <uri>http://www.andrejkoelewijn.com/</uri>
        </author>
        <content type="html">&lt;p&gt;JProfiler is a Java profiler which can give you insight into what a running application is doing: which methods are consuming the most cpu, how many objects are created, etc. Jprofiler also shows you information about jdbc calls and sql statements executed by your java application.&lt;/p&gt;

&lt;p&gt;Setting up Jprofiler to profile a Mendix runtime is easy, you can start profiling a running Mendix runtime, without reconfiguration or restarting the application.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://resources.ej-technologies.com/jprofiler/help/doc/help.pdf&quot;&gt;installation guide&lt;/a&gt; provides a more complete manual, but the basic steps are:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;download and install Jprofiler on a desktop, this will be the client gui&lt;/li&gt;
  &lt;li&gt;download and unzip Jprofiler on your server, start bin/jpenable (see see section B.3.10 Attaching To JVM of the manual)&lt;/li&gt;
  &lt;li&gt;Start the client on your desktop, connect to a remote server on the port indicated by jpenable&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here are some screenshots:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Choose to profile an application on a remote server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2014/01/jprofiler/1-profile-remote-app.png&quot; alt=&quot;Profile remote app&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;My Mendix application is running in a virtual machine running Linux&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2014/01/jprofiler/2-remote-linux.png&quot; alt=&quot;Remote Linux&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Choose which Java you are using&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2014/01/jprofiler/3-choose-jvm.png&quot; alt=&quot;Choose JVM&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I&amp;rsquo;ve already started the Mendix runtime&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2014/01/jprofiler/4-start-app-immediately.png&quot; alt=&quot;Start app immediately&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;IP Address of my virtual machine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2014/01/jprofiler/5-remote-address.png&quot; alt=&quot;Remote address&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Directory in the virtual machine where i unzipped Jprofiler&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2014/01/jprofiler/6-remote-directory.png&quot; alt=&quot;Remote directory&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;This is the port returned by running bin/jpenable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2014/01/jprofiler/7-profiling-port.png&quot; alt=&quot;Profiling port&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Start&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2014/01/jprofiler/8-start-jprofiler.png&quot; alt=&quot;Start Jprofiler&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Choose how you want Jprofiler to collect information about your application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2014/01/jprofiler/9-initial-profiling-settings.png&quot; alt=&quot;Initial profiling settings&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;This is just default setup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2014/01/jprofiler/10-profiling-setup.png&quot; alt=&quot;Profiling setup&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;And finally where looking at some data collected by Jprofiler&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2014/01/jprofiler/11-objects.png&quot; alt=&quot;Objects&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I currently have 4 database connections&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2014/01/jprofiler/12-jdbc-timeline.png&quot; alt=&quot;JDBC timeline&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;JDBC Hotspots shows the heaviest SQL statements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2014/01/jprofiler/13-jdbc-hotspots.png&quot; alt=&quot;JDBC hotsports&quot; /&gt;&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <title>Dynamische Architectuur Visualisaties</title>
        <link href="http://www.andrejkoelewijn.com/blog/2013/11/30/dynamische-architectuur-visualisaties/" type="text/html" rel="alternate"/>
        <published>2013-11-30T00:00:00+01:00</published>
        <updated>2013-11-30T00:00:00+01:00</updated>
        <id>http://www.andrejkoelewijn.com/blog/2013/11/30/dynamische-architectuur-visualisaties</id>
        <author>
          <name>Andrej Koelewijn</name>
          <uri>http://www.andrejkoelewijn.com/</uri>
        </author>
        <content type="html">&lt;p&gt;Tijdens het &lt;a href=&quot;http://www.laccongres.nl/programma-2013/&quot;&gt;LAC-2013&lt;/a&gt; heb ik een presentatie verzorgd over &lt;a href=&quot;/blog/images/2013/lac2013/index.html&quot;&gt;Dynamische Architectuur Visualisatie&lt;/a&gt;. Tijdens deze presentatie heb ik laten zien hoe ik schetsen in SVG formaat gebruik als visuele ondersteuning van een presentatie. De svg versie van deze presentatie zie je hieronder. De volgende pagina biedt de mogelijkheid om slides van de presentatie te bookmarken, of the mailen: &lt;a href=&quot;/blog/images/2013/lac2013/index.html&quot;&gt;Dynamische Architectuur Visualisatie&lt;/a&gt;. Source code van de library staat op github: &lt;a href=&quot;https://github.com/ako/inkscape-presenter&quot;&gt;Inkscape presenter&lt;/a&gt;.&lt;/p&gt;

&lt;embed src=&quot;/blog/images/2013/lac2013/lac2013.svg&quot; class=&quot;col-md-12&quot; /&gt;

</content>
    </entry>
    
    <entry>
        <title>Monitoring Mendix using JMX</title>
        <link href="http://www.andrejkoelewijn.com/blog/2013/11/18/monitoring-mendix-using-jmx/" type="text/html" rel="alternate"/>
        <published>2013-11-18T00:00:00+01:00</published>
        <updated>2013-11-18T00:00:00+01:00</updated>
        <id>http://www.andrejkoelewijn.com/blog/2013/11/18/monitoring-mendix-using-jmx</id>
        <author>
          <name>Andrej Koelewijn</name>
          <uri>http://www.andrejkoelewijn.com/</uri>
        </author>
        <content type="html">&lt;p&gt;The following is only relevant if you run &lt;a href=&quot;http://www.mendix.com/&quot;&gt;Mendix&lt;/a&gt; on-premises. If you do, you probably have standard monitoring tooling that you use to monitor all your applications.&lt;/p&gt;

&lt;p&gt;For java applications most monitoring tools provide a way to hook into &lt;a href=&quot;http://www.oracle.com/technetwork/java/javase/tech/javamanagement-140525.html&quot;&gt;JMX&lt;/a&gt; to get information about the application. The following describes how you can use JMX to get information on your Mendix application.&lt;/p&gt;

&lt;p&gt;Mendix doesn&amp;rsquo;t provide any runtime or application specific MBeans, which means that without writing your own MBeans you will only be able to monitor generic JVM statistics. In this post i&amp;rsquo;ll describe how you enable JMX on your Mendix runtime. I&amp;rsquo;ll also decribe how you can write custom MBeans to expose Mendix runtime information and application specific information.&lt;/p&gt;

&lt;p&gt;This post will discuss the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Starting the Mendix runtime with JMX enabled&lt;/li&gt;
  &lt;li&gt;MBean exposing generic Mendix statistics&lt;/li&gt;
  &lt;li&gt;MBean exposing application specific statistics&lt;/li&gt;
  &lt;li&gt;Register MBeans using a Startup microflow&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;starting-the-mendix-runtime-with-jmx-enabled&quot;&gt;Starting the Mendix runtime with JMX enabled&lt;/h3&gt;

&lt;p&gt;To enable JMX on your Mendix runtime you can use the following javaopts to the m2ee.yaml for your Mendix runtime:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; javaopts: [
   &quot;-Dfile.encoding=UTF-8&quot;, &quot;-XX:MaxPermSize=64M&quot;, &quot;-Xmx128M&quot;, &quot;-Xms128M&quot;,
   &quot;-Djava.io.tmpdir=/tmp&quot;,
   &quot;-Dcom.sun.management.jmxremote&quot;,
   &quot;-Dcom.sun.management.jmxremote.port=7845&quot;,
   &quot;-Dcom.sun.management.jmxremote.local.only=false&quot;,
   &quot;-Dcom.sun.management.jmxremote.authenticate=false&quot;,
   &quot;-Dcom.sun.management.jmxremote.ssl=false&quot;,
   &quot;-Djava.rmi.server.hostname=192.168.1.70&quot;,
 ]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After you restart the Mendix runtime you will be able to connect to it using tools like &lt;a href=&quot;http://docs.oracle.com/javase/7/docs/technotes/guides/management/jconsole.html&quot;&gt;JConsole&lt;/a&gt; or &lt;a href=&quot;http://visualvm.java.net/&quot;&gt;VisualVM&lt;/a&gt;. Every JVM by default exposes information like memory usage, garbage collection and threading. If you want more, you can write you own &lt;a href=&quot;http://docs.oracle.com/javase/tutorial/jmx/mbeans/standard.html&quot;&gt;MBeans&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;mbean-exposing-generic-mendix-statistics&quot;&gt;MBean exposing generic Mendix statistics&lt;/h3&gt;

&lt;p&gt;The simplest way to expose management information is by writing a MBean interface and a Java class which implements the interface. You can define getters and setter, but you can also define methods which can be called from generic management tooling. I&amp;rsquo;ve used this for example to tell a running application to reload its configuration file.&lt;/p&gt;

&lt;p&gt;Example of an interface which contains getters for some generic Mendix information, MxStatsMBean.java:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package jmx.actions;
public interface MxStatsMBean {
    public int getMaximumNumberConcurrentUsers() throws Exception;
    public int getActionQueueSize();
    public int getActiveActionCount();
    public int getScheduledActionCount();
    public long getNumberConcurrentSessions();
    public long getCurrentUserCount();
    public long getCompletedActionCount();
    public long getNamedUserCount();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And here is the implementation, MxStats.java. The methods just call the &lt;a href=&quot;http://apidocs.mendix.com/4/runtime/classcom_1_1mendix_1_1core_1_1_core.html&quot;&gt;Mendix Core&lt;/a&gt; class, and return the value:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package jmx.actions;
import com.mendix.core.Core;
public class MxStats implements MxStatsMBean {
    public int getMaximumNumberConcurrentUsers() throws Exception {
            return Core.getMaximumNumberConcurrentUsers();
    }
    public int getActionQueueSize(){
        return Core.getActionQueueSize();
    }
    public int getActiveActionCount(){
        return Core.getActiveActionCount();
    }
    public int getScheduledActionCount(){
        return Core.getScheduledActionCount();
    }
    public long getNumberConcurrentSessions(){
        return Core.getNumberConcurrentSessions();
    }
    public long getCurrentUserCount(){
        return Core.getConcurrentUserCount(true);
    }
    public long getCompletedActionCount(){
        return Core.getCompletedActionCount();
    }
    public long getNamedUserCount(){
        return Core.getNamedUserCount();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here&amp;rsquo;s a screenshot of JConsole showing the values exposed by this MBean:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2013/jconsole-mendix.png&quot; alt=&quot;JConsole Mendix&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;mbean-exposing-application-specific-statistics&quot;&gt;MBean exposing application specific statistics&lt;/h3&gt;

&lt;p&gt;You can use the same approach, with an Interface and implementation class, to also expose application specific information. Here&amp;rsquo;s a different approach: one that exposes a dynamic set of values. You can do the same with methods, but the example only shows attributes to retrieve values.&lt;/p&gt;

&lt;p&gt;The idea is that you will have a Java Action that you can call in a microflow, where you expose arbitrary key, value pairs. Here&amp;rsquo;s an example in the Mendix modeler:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2013/setstat.png&quot; alt=&quot;Microflow to change application statistic&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The implementation of the SetJmxValue looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package jmx.actions;
public class SetJmxValue extends CustomJavaAction&amp;lt;Boolean&amp;gt;
{
  private String name;
  private Long value;
  public SetJmxValue(IContext context, String name, Long value)
  {
    super(context);
    this.name = name;
    this.value = value;
  }
  @Override
  public Boolean executeAction() throws Exception
  {
    // BEGIN USER CODE
    MxAppStats.setLongValue(name,value);
    return true;
    // END USER CODE
  }
  /* .... */
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The real meat is in the MxAppStats class. Here i use a HashMap to store all the key,value pairs that will be exposed. The HashMap is implemented as a static property, so this will be runtime instance specific (for production you&amp;rsquo;ll want to make this code thread-save, which it currently isn&amp;rsquo;t).  GetMBeanInfo returns the data which tells the monitoring software which properties are exposed in this MBean.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package jmx.actions;

import javax.management.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Vector;

public class MxAppStats implements DynamicMBean {

    private static HashMap stats;

    @Override
    public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException {
        return getStats().get(attribute);
    }

    @Override
    public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
        getStats().put(attribute.getName(), attribute.getValue());
    }

    @Override
    public AttributeList getAttributes(String[] attributes) {
        AttributeList list = new AttributeList();
        for (Object name : getStats().keySet()) {
            list.add(new Attribute((String) name, getStats().get(name)));
        }
        return list;
    }

    @Override
    public AttributeList setAttributes(AttributeList attributes) {
        return null;
    }

    @Override
    public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException {
        return null;
    }

    @Override
    public MBeanInfo getMBeanInfo() {
        //MBeanAttributeInfo[] attrs = new MBeanAttributeInfo[getStats().size()];
        ArrayList&amp;lt;MBeanAttributeInfo&amp;gt; attrs = new ArrayList();
        for (Object name : getStats().keySet()) {
            MBeanAttributeInfo attr = new MBeanAttributeInfo(
                    (String) name,
                    &quot;java.lang.Long&quot;,
                    &quot;Property &quot; + name,
                    true,
                    true,
                    false
            );
            attrs.add(attr);
        }
        MBeanInfo info = new MBeanInfo(
                this.getClass().getName(),
                &quot;Mendix App MBean&quot;,
                (MBeanAttributeInfo[]) attrs.toArray(new MBeanAttributeInfo[0]),
                null,
                null,
                null
        );
        return info;
    }

    public static void setLongValue(String name, Long value) {
        getStats().put(name, value);
    }

    private static HashMap getStats() {
        if (stats == null) {
            stats = new HashMap();
        }
        return stats;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;register-the-mbeans-using-a-startup-microflow&quot;&gt;Register the MBeans using a Startup microflow&lt;/h3&gt;

&lt;p&gt;You need to register your MBean with the MBeanServer, before they can be used. We will call the initialization code in a Startup Microflow.&lt;/p&gt;

&lt;p&gt;First we need to create a microflow:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2013/MF_SetupJmx.png&quot; alt=&quot;JMX Setup Microflow&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now we can call it in the startup of the Mendix runtime:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2013/after_startup.png&quot; alt=&quot;After Startup JMX Microflow&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And the java code for the InitJMX action:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@Override
public Boolean executeAction() throws Exception
{
  // BEGIN USER CODE
      initJmx();
      return true;
  // END USER CODE
}
// BEGIN EXTRA CODE
  private MBeanServer mbs = null;
  private void initJmx() throws NotCompliantMBeanException, InstanceAlreadyExistsException, MBeanRegistrationException, MalformedObjectNameException {
  mbs = ManagementFactory.getPlatformMBeanServer();
  /*
   * runtime statistics
   */
  MxStatsMBean mxStats = new MxStats();
  ObjectName mxMbeanName = new ObjectName(&quot;Mx:name=MxMbean&quot;);
  mbs.registerMBean(mxStats, mxMbeanName);
  /*
   * application statistics
   */
  MxAppStats appStats = new MxAppStats();
  ObjectName mxAppMbeanName = new ObjectName(&quot;Mx:name=MxAppMbean&quot;);
  mbs.registerMBean(appStats, mxAppMbeanName);
  }
// END EXTRA CODE
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;JMX is the default Java way to expose information to monitoring tooling, so there are lots of options besides JConsole and VisualVM. There&amp;rsquo;s command line tooling like &lt;a href=&quot;http://wiki.cyclopsgroup.org/jmxterm&quot;&gt;jmxterm&lt;/a&gt;, or complete monitoring suites like Hyperic HQ, Hawt.io, and &lt;a href=&quot;http://www.jboss.org/rhq&quot;&gt;RHQ&lt;/a&gt;. Other well know monitoring tooling like &lt;a href=&quot;http://apps.splunk.com/app/668/&quot;&gt;Splunk&lt;/a&gt; and &lt;a href=&quot;https://docs.newrelic.com/docs/java/custom-jmx-monitoring-by-yml&quot;&gt;New Relic&lt;/a&gt; also offer ways to feed it JMX data. Or you can create something cutting edge using &lt;a href=&quot;http://logstash.net/&quot;&gt;Logstash&lt;/a&gt;, &lt;a href=&quot;https://docs.newrelic.com/docs/java/custom-jmx-monitoring-by-yml&quot;&gt;jmxtrans&lt;/a&gt;, &lt;a href=&quot;http://www.elasticsearch.org/&quot;&gt;ElasticSearch&lt;/a&gt; and &lt;a href=&quot;http://demo.kibana.org/#/dashboard&quot;&gt;Kibana&lt;/a&gt;.&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <title>Testing Mendix applications using Selenium</title>
        <link href="http://www.andrejkoelewijn.com/blog/2013/10/05/testing-mendix-applications-using-selenium/" type="text/html" rel="alternate"/>
        <published>2013-10-05T00:00:00+02:00</published>
        <updated>2013-10-05T00:00:00+02:00</updated>
        <id>http://www.andrejkoelewijn.com/blog/2013/10/05/testing-mendix-applications-using-selenium</id>
        <author>
          <name>Andrej Koelewijn</name>
          <uri>http://www.andrejkoelewijn.com/</uri>
        </author>
        <content type="html">&lt;p&gt;&lt;a href=&quot;http://docs.seleniumhq.org/&quot;&gt;Selenium&lt;/a&gt; is a useful tool for automating functional tests. In this post i&amp;rsquo;ll show you some tips and tricks about using Selenium IDE with &lt;a href=&quot;http://www.mendix.com/&quot;&gt;Mendix&lt;/a&gt;. Selenium IDE is a Firefox plugin that enables you to record whatever you are doing in Firefox, so that you can repeat these steps as a test script.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2013/selenium-ide.png&quot; alt=&quot;Selenium IDE&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You can use Selenium IDE to record tests scripts, but these scripts need to be edited before you can use them:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Replace id targets with xpath targets&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;Most buttons you can target by the text in the button&lt;/p&gt;

        &lt;pre&gt;&lt;code&gt;mouseDown //button[text()=&#39;New&#39;]
&lt;/code&gt;&lt;/pre&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Mendix 4 buttons aren&amp;rsquo;t implemented using a button tag, but use a series of nested divs and spans. Also, the mouseDown event handler doesn&amp;rsquo;t trigger execute the logic behind the button. Keypress with a return keySequence on the top div does the trick. (&lt;em&gt;Tip:&lt;/em&gt; &lt;em&gt;Inspect Element&lt;/em&gt; in Google Chrome has a tab called &lt;em&gt;Event Listeners&lt;/em&gt; which lists all the event handlers of an html element.)&lt;/p&gt;

        &lt;pre&gt;&lt;code&gt;keyPress //div[contains(@class,&#39;mendix_Button&#39;)][.//span[text()=&#39;New&#39;]] \\13
&lt;/code&gt;&lt;/pre&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;You can target input fields by the label before it:&lt;/p&gt;

        &lt;pre&gt;&lt;code&gt;type //input[ancestor::tr/th/label=&#39;Omschrijving&#39;] test-value
&lt;/code&gt;&lt;/pre&gt;

        &lt;p&gt;This xpath expression selects the input element, which is in a table row, that has a table header containing a label &lt;em&gt;Omschrijving&lt;/em&gt;.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;If you have a form with multiple columns, you can use the following xpath:&lt;/p&gt;

        &lt;pre&gt;&lt;code&gt;type //input[preceding::th[1]/label=&#39;Omschrijving&#39;] test-value 
&lt;/code&gt;&lt;/pre&gt;

        &lt;p&gt;This xpath expression tells Selenium to select the input field where the closest preceding table header contains a label &lt;em&gt;Omschrijving&lt;/em&gt;.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;To choose a value from a dropdown list:&lt;/p&gt;

        &lt;pre&gt;&lt;code&gt;select //select[preceding::th/label=&#39;Af Bij&#39;] label=Af
&lt;/code&gt;&lt;/pre&gt;

        &lt;p&gt;This selects the value Af from a dropdown list preceded bij a label &lt;em&gt;Af Bij&lt;/em&gt;.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;To edit an entity from a DataGrid table, you can use the following:&lt;/p&gt;

        &lt;pre&gt;&lt;code&gt;waitForElementPresent //table//tr/td/div[text()=&#39;test-transactie-1&#39;]
doubleClick //table//tr/td/div[text()=&#39;test-transactie-1&#39;]
&lt;/code&gt;&lt;/pre&gt;

        &lt;p&gt;This will cause a double click on a tablecell containing the text &lt;em&gt;test-transactie-1&lt;/em&gt;.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Replace most mouse clicks with mouseDown mouseUp. To click on a button you need the following commands:&lt;/p&gt;

    &lt;pre&gt;&lt;code&gt;mouseDown //label[text()=&#39;Save&#39;]
mouseUp //label[text()=&#39;Save&#39;]
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;Btw, you don&amp;rsquo;t need to do this for popup alter windows. Here you can use click:&lt;/p&gt;

    &lt;pre&gt;&lt;code&gt;click //button[text()=&#39;OK&#39;] 
&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Add a fireEvent blur after typing text in an input field:&lt;/p&gt;

    &lt;pre&gt;&lt;code&gt;fireEvent //input[preceding::th[1]/label=&#39;Btw percentage&#39;] blur
&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Add waitForElementPresent commands, for example:&lt;/p&gt;

    &lt;pre&gt;&lt;code&gt;waitForElementPresent //button[text=&#39;New&#39;]
waitForElementPresent //h1[text()=&#39;Boek&#39;]
&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;An ofcourse, a test script wouldn&amp;rsquo;t be complete without some actual tests:&lt;/p&gt;

    &lt;pre&gt;&lt;code&gt;verifyValue //input[preceding::th[1]/label=&#39;Bon nummer&#39;] 123
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;This verifies that the page contains an input field preceded by a label &lt;em&gt;Bon nummer&lt;/em&gt; contains the value 123.&lt;/p&gt;

    &lt;pre&gt;&lt;code&gt;assertVisible //table//tr/td/div[text()=&#39;inkoop-1-checked&#39;]
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;This checks a table cell contains the value &lt;em&gt;inkoop-1-checked&lt;/em&gt;.&lt;/p&gt;

    &lt;pre&gt;&lt;code&gt;assertVisible //h1[text()=&#39;Edit Boek&#39;]
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;This verifies that the page contains a header with the text &lt;em&gt;Edit Boek&lt;/em&gt;.&lt;/p&gt;

    &lt;pre&gt;&lt;code&gt;assertVisible //div[@class=&#39;alert alert-error&#39;][text()=&#39;Invalid currency&#39;]
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;This verifies that the page contains an error message with the text &lt;em&gt;Invalid currency&lt;/em&gt;.&lt;/p&gt;

    &lt;pre&gt;&lt;code&gt;assertElementNotPresent //dev[@class=&#39;alert alert-error&#39;]
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;This verifies that the page doesn&amp;rsquo;t contain any error messages.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This has been tested with Mendix 5.0.0 beta 7. You&amp;rsquo;ll probably need different xpath expressions for other versions of Mendix. Firefox inspector is a useful tool for inspecting the generated html to determine the correct xpath expressions.&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <title>Debugging with webstorm and karma</title>
        <link href="http://www.andrejkoelewijn.com/blog/2013/05/07/debugging-with-webstorm-and-karma/" type="text/html" rel="alternate"/>
        <published>2013-05-07T00:00:00+02:00</published>
        <updated>2013-05-07T00:00:00+02:00</updated>
        <id>http://www.andrejkoelewijn.com/blog/2013/05/07/debugging-with-webstorm-and-karma</id>
        <author>
          <name>Andrej Koelewijn</name>
          <uri>http://www.andrejkoelewijn.com/</uri>
        </author>
        <content type="html">&lt;p&gt;I think this is not mentioned in Vojta&amp;rsquo;s &lt;a href=&quot;http://www.youtube.com/watch?v=MVw8N3hTfCI&quot;&gt;testacular&lt;/a&gt; video, or maybe I missed it, but i had to install &lt;a href=&quot;https://chrome.google.com/webstore/detail/jetbrains-ide-support/hmhgeddbohgjknpmjagkdomcpobmllji&quot;&gt;JetBrain&amp;rsquo;s chrome debugger plugin&lt;/a&gt; to be able to debug tests run with Karma in Webstorm.&lt;/p&gt;

&lt;p&gt;The steps i used to get it to work:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Install chrome &lt;a href=&quot;https://chrome.google.com/webstore/detail/jetbrains-ide-support/hmhgeddbohgjknpmjagkdomcpobmllji&quot;&gt;Jetbrains IDE support plugin&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Configure a Karma Server run configuration in Webstorm:
&lt;img src=&quot;/blog/images/2013/webstorm-karma-server.png&quot; alt=&quot;Webstorm Karma Server run configuration&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Configure a Karma debug configuration in Webstorm:
&lt;img src=&quot;/blog/images/2013/webstorm-karma-debug.png&quot; alt=&quot;Webstorm Karma debug configuration&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Run Karma server
&lt;img src=&quot;/blog/images/2013/webstorm-karma-server-run.png&quot; alt=&quot;Webstorm Karma Server run&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Run Karma debug
&lt;img src=&quot;/blog/images/2013/webstorm-karma-debug-run.png&quot; alt=&quot;Webstorm Karma debug run&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;small-example&quot;&gt;Small example&lt;/h4&gt;

&lt;p&gt;Create project folder&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;npm install -g karma
mkdir test-karma
cd test-karma
mkdir app
mkdir app/js
mkdir app/lib
cp &amp;lt;angular library&amp;gt; app/lib/angular.min.js
mkdir config
mkdir test
mkdir test/unit
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Edit app/index.html&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;!doctype html&amp;gt;
&amp;lt;html ng-app&amp;gt;
	&amp;lt;head&amp;gt;
	    &amp;lt;title&amp;gt;Hello World&amp;lt;/title&amp;gt;
	    &amp;lt;script src=&quot;lib/angular.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
	    &amp;lt;script src=&quot;js/app.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
	&amp;lt;/head&amp;gt;
	&amp;lt;body ng-controller=&quot;HelloWorldCtrl&quot;&amp;gt;
	    &amp;lt;p&amp;gt;Hello &amp;lt;/p&amp;gt;
	    &amp;lt;input id=&quot;name&quot; name=&quot;name&quot; type=&quot;text&quot; ng-model=&quot;name&quot; 
	           placeholder=&quot;What&#39;s your name?&quot;/&amp;gt;
	     &amp;lt;a href=&quot;#&quot; ng-click=&quot;reset();&quot;&amp;gt;Reset&amp;lt;/a&amp;gt;
	&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Edit app/js/app.js&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;function HelloWorldCtrl($scope) {
	$scope.reset = function(){
	    $scope.name = &quot;&quot;;
	};
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Edit test/unit/HelloWorldCtrlSpec.js&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;describe(&#39;HelloWorld controller&#39;,function(){
	it(&#39;Should reset name value&#39;,function(){
		var scope = {},
			ctrl = new HelloWorldCtrl(scope);
		scope.name = &quot;john&quot;;
		scope.reset();
		expect(scope.name).toBe(&quot;&quot;);
	});
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Create a karma configuration file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$&amp;gt; karma init config/karma.conf.js

    Which testing framework do you want to use ?
    &amp;gt; jasmine
    Do you want to use Require.js ?
    &amp;gt; no
    Do you want to capture a browser automatically ?
    &amp;gt; Chrome
    Which files do you want to test ?
    &amp;gt; test/**/*Spec.js
    Any files you want to exclude ?
    &amp;gt; 
    Do you want Testacular to watch all the files and run the tests on change ?
    &amp;gt; yes
    Config file generated at &quot;/home/akoelewijn/projects/training-angularjs/test-karma/config/karma.conf.js&quot;.
&lt;/code&gt;&lt;/pre&gt;

</content>
    </entry>
    
    <entry>
        <title>Five examples why every tablet needs a camera</title>
        <link href="http://www.andrejkoelewijn.com/blog/2013/01/21/Five-examples-why-every-tablet-needs-camera/" type="text/html" rel="alternate"/>
        <published>2013-01-21T00:00:00+01:00</published>
        <updated>2013-01-21T00:00:00+01:00</updated>
        <id>http://www.andrejkoelewijn.com/blog/2013/01/21/Five-examples-why-every-tablet-needs-camera</id>
        <author>
          <name>Andrej Koelewijn</name>
          <uri>http://www.andrejkoelewijn.com/</uri>
        </author>
        <content type="html">&lt;p&gt;There are a lot of people who think camera&amp;rsquo;s in tablets are a bad idea. &amp;ldquo;Nobody should be allowed to take pictures with a large tablet in front of their face.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;But if you can think outside of the traditional camera box for a moment, and start to think what&amp;rsquo;s possible if you combine a really portable computer with a decent camera, you&amp;rsquo;ll soon see interesting new possibilities.&lt;/p&gt;

&lt;p&gt;Just a couple examples:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://www.intsig.com/en/camscanner.html&quot;&gt;Camscanner&lt;/a&gt; - turns your tablet or smartphone into a scanner. You take a picture of your notes using camscanner, it enhances the contrast and readability, and truns it into a pdf. Great tool if you still prefer to take notes with traditional pen and paper, but would like to store your notes digitally.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://popapp.in/&quot;&gt;POP prototyping&lt;/a&gt; - turns your paper mockups into &lt;a href=&quot;http://www.fastcodesign.com/1671490/design-your-app-on-paper-animate-it-with-your-iphone-camera&quot;&gt;clickable digital mockups&lt;/a&gt;. You just draw your mockups on pen and paper, take some pictures, and add some interaction: what screen should be displayed when you press somewhere on your paper mockup?&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://www.sensopia.com/english/index.html&quot;&gt;Magicplan&lt;/a&gt; - Take a picture of all the corners of a room, and Magicplan automatically draws a map of the room. Magicplan also calculates the size of your room. Would be even nicer if you could integrate it with something like Google sketchup and create 3d models of your rooms. I bet there&amp;rsquo;s an app for that?&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://itunes.apple.com/us/app/puppet-pals-hd/id342076546?mt=8&quot;&gt;Puppetpals&lt;/a&gt; - Nice app to create animated stories. What makes it really nice is that you can take pictures of the people around you and quickly add them into your story.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://www.dermomap.com/features&quot;&gt;DermoMap&lt;/a&gt; - Application to help diagnosing skin problems. It offers information on all sorts of skin diseases. Using the camera, a picture of a skin problem can be used in the application to compare it with available pictures.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There&amp;rsquo;s probably a lot more things you do with a computer that would benefit from direct access to a camera. It&amp;rsquo;s certainly a lot faster and easier than having to take a picture with another device and then getting the picture into the application where you need it.&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <title>Time to toss out the laptop?</title>
        <link href="http://www.andrejkoelewijn.com/blog/2013/01/07/time-to-toss-out-the-laptop/" type="text/html" rel="alternate"/>
        <published>2013-01-07T00:00:00+01:00</published>
        <updated>2013-01-07T00:00:00+01:00</updated>
        <id>http://www.andrejkoelewijn.com/blog/2013/01/07/time-to-toss-out-the-laptop</id>
        <author>
          <name>Andrej Koelewijn</name>
          <uri>http://www.andrejkoelewijn.com/</uri>
        </author>
        <content type="html">&lt;p&gt;While converting my old wordpress blogposts to markdown i read some of my old 
posts. For example, here is what i &lt;a href=&quot;/blog/2007/06/29/apple-iphone-day/&quot;&gt;wrote when Apple launched the iPhone in 2007&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In a couple of years mobile phones will be powerful enough to replace 
laptops for most common computing usages. You won’t need a separate laptop. 
You walk around with your mobile phone, in the office or at home you put it 
in a docking station, attach a keyboard and a bigger display, and you have 
all the computing power you need.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Some news this last week indicates we&amp;rsquo;re getting close to that point: &lt;a href=&quot;http://www.theverge.com/2013/1/6/3844860/nvidia-tegra-4-announcement-specs-availability&quot;&gt;76 cores in a mobile cpu&lt;/a&gt; &amp;amp; 
&lt;a href=&quot;http://arstechnica.com/gadgets/2013/01/canonical-unveils-ubuntu-phone-os-that-doubles-as-a-full-pc/&quot;&gt;desktop OS for phones&lt;/a&gt;.&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <title>Moving from Wordpress to Jekyll</title>
        <link href="http://www.andrejkoelewijn.com/blog/2013/01/03/moving-from-wordpress-to-jekyll/" type="text/html" rel="alternate"/>
        <published>2013-01-03T00:00:00+01:00</published>
        <updated>2013-01-03T00:00:00+01:00</updated>
        <id>http://www.andrejkoelewijn.com/blog/2013/01/03/moving-from-wordpress-to-jekyll</id>
        <author>
          <name>Andrej Koelewijn</name>
          <uri>http://www.andrejkoelewijn.com/</uri>
        </author>
        <content type="html">&lt;p&gt;&lt;em&gt;Work in progress&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m a slow mover here, far behind the hype-curve, but this blog is currently being moved to jekyll. The following are some notes and links from this process.&lt;/p&gt;

&lt;p&gt;Reasons to migrate:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Cheaper hosting - this blog is currently hosted on DreamHost. By migrating to a static site using Jekyll, cheaper options become available, for example Amazon S3 or Github.&lt;/li&gt;
  &lt;li&gt;Learn something new -10 years ago this blog started on Moveable Type, which also generated static html pages. In 10 years we&amp;rsquo;ve gone from full dynamic back to static, mostely thanks to javascript. The dynamic parts in many pages can be generated using javascript and external APIs. I wanted to see how well this works using Jekyll and S3.&lt;/li&gt;
  &lt;li&gt;Security - Wordpress blogs are a frequent target of attacks, my weblog has been hacked once so far. A static website should be a lot more secure. I&amp;rsquo;m also trying Cloudflare as an extra defence mechanism.&lt;/li&gt;
  &lt;li&gt;Speed - A static website should be a bit faster than a dynamically generated wordpress site. Also interested to see if Cloudflare speeds up things.&lt;/li&gt;
  &lt;li&gt;Readability - it&amp;rsquo;s time for a cleaner design, i do most of my reader on a tablet these days. I want to create a better reading experience on tablets by removing all the sidebars, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some usefull links i&amp;rsquo;ve found:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://paulstamatiou.com/how-to-wordpress-to-jekyll&quot;&gt;How To: WordPress to Jekyll&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://vitobotta.com/how-to-migrate-from-wordpress-to-jekyll/&quot;&gt;Migrating from Wordpress to Jekyll - Part 2: Everything you need to know about Jekyll&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.codeography.com/2009/03/30/getting-started-with-jekyll.html&quot;&gt;Getting Started with Jekyll&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://vvv.tobiassjosten.net/development/jekyll-blog-on-amazon-s3-and-cloudfront/&quot;&gt;Jekyll blog on Amazon S3 and CloudFront&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://nb.nathanamy.org/2012/04/rsyncing-jekyll/&quot;&gt;Rsyncing Jekyll&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;converting-wordpress-posts&quot;&gt;converting wordpress posts&lt;/h5&gt;

&lt;p&gt;This is where is spent most of my time. There are automatic conversion scripts, but i still need to do a bit of manual work on every post to create nice markdown formatted posts.&lt;/p&gt;

&lt;p&gt;The following gedit external tool script helps converting html posts to markdown posts:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/bin/sh
sed &#39;s/\r//g&#39; | \
  sed &#39;s/\[sourcecode.*\]/&amp;lt;pre&amp;gt;&amp;lt;code&amp;gt;/g&#39; | \
  sed &#39;s/\[\/sourcecode\]/&amp;lt;\/pre&amp;gt;&amp;lt;\/code&amp;gt;/g&#39; | \
  sed &#39;s/\[code.*\]/&amp;lt;pre&amp;gt;&amp;lt;code&amp;gt;/g&#39; | \
  sed &#39;s/\[\/code\]/&amp;lt;\/pre&amp;gt;&amp;lt;\/code&amp;gt;/g&#39; | \
  sed &#39;s/^$/&amp;lt;div\/&amp;gt;/g&#39; | \
  pandoc -f html -t markdown --reference-links --indented-code-classes=code
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Some manual changes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Replace image links. &lt;/li&gt;
  &lt;li&gt;Modify embed tags used to include svg images. Now using image tags.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is much cleaner post text.&lt;/p&gt;

&lt;h5 id=&quot;syntax-highlighting&quot;&gt;syntax highlighting&lt;/h5&gt;

&lt;p&gt;You can do code highlighting when generating the static pages using one of the 
markdown engines. I&amp;rsquo;ve chosen to implement it client side, leaving the generated
html as clean as possible. &lt;/p&gt;

&lt;p&gt;[Google code prettify] will determine the correct programming language so you
don&amp;rsquo;t have to specify it yourself. The following javascript lines enable prettify
on all pre tags:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$(document).ready(function(){
    $(&quot;pre&quot;).addClass(&quot;prettyprint&quot;);
    prettyPrint();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;h5 id=&quot;images&quot;&gt;Images&lt;/h5&gt;

&lt;p&gt;Automatic conversion of image links in html to markdown didn&amp;rsquo;t work as well as i hoped. The following was created for html links showing a thumbnail image and linking to a fullsize image:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[![][]][]
[![][]]: http://www.andrejkoelewijn.com/wp/wp-content/uploads/2010/03/Screenshot-1.png
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I manually replaced these with the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[![screenshot alt text][screenshot thumbnail]][screenshot]
[screenshot]: http://www.andrejkoelewijn.com/blog/images/2010/03/Screenshot-1.png
[screenshot thumbnail]: http://www.andrejkoelewijn.com/blog/images/2010/03/Screenshot-1-320x240.png
&lt;/code&gt;&lt;/pre&gt;

&lt;h5 id=&quot;comments&quot;&gt;Comments&lt;/h5&gt;

&lt;p&gt;Disqus&lt;/p&gt;

&lt;p&gt;Keep url the same
    comments:true
Add disqus javascript to post template&lt;/p&gt;

&lt;h5 id=&quot;objects&quot;&gt;Objects&lt;/h5&gt;

&lt;p&gt;Svg animations using objects - replaced by img tag, link to html page with object
Problems with html generation using kramdown&lt;/p&gt;

&lt;h5 id=&quot;search&quot;&gt;Search&lt;/h5&gt;

&lt;p&gt;&lt;a href=&quot;http://www.google.com/cse&quot;&gt;Google Custom Search Engine&lt;/a&gt;&lt;/p&gt;

&lt;h5 id=&quot;social-buttons&quot;&gt;Social buttons&lt;/h5&gt;

&lt;p&gt;&lt;a href=&quot;http://socialitejs.com/&quot;&gt;Socialite.js&lt;/a&gt;&lt;/p&gt;

&lt;h5 id=&quot;urls&quot;&gt;Urls&lt;/h5&gt;

&lt;p&gt;url in wordpress everything is path, no resource:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;http://www.andrejkoelewijn.com/wp/2010/03/05/jee-cdi-tip-target-unreachable-identifier-resolved-to-null/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Default in jekyll, ends with html page:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;http://www.andrejkoelewijn.com/blog/2013/01/03/moving-from-wordpress-to-jekyll.html
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This can be configured in _config.yml&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;permalink:   pretty
&lt;/code&gt;&lt;/pre&gt;

&lt;h5 id=&quot;javascript&quot;&gt;Javascript&lt;/h5&gt;

&lt;p&gt;Javascript libraries are used from CDNJS&lt;/p&gt;

&lt;h5 id=&quot;upload-to-dreamhost&quot;&gt;Upload to Dreamhost&lt;/h5&gt;

&lt;p&gt;For now this weblog is still hosted on Dreamhost, i&amp;rsquo;ll look into S3 when the migration to Jekyll has been completed.&lt;/p&gt;

&lt;p&gt;Deployment is done using rsync:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;rsync --progress --compress --recursive --checksum --delete _site/ user@host.tld:public_html/
&lt;/code&gt;&lt;/pre&gt;

&lt;h5 id=&quot;caching-with-cloudflare&quot;&gt;Caching with CloudFlare&lt;/h5&gt;

&lt;p&gt;Cloudflare CDN to cache all content
Pagerule to host html pages: www.andrejkoelewijn.com/wp/20&lt;em&gt;/&lt;/em&gt;/&lt;em&gt;/&lt;/em&gt;/&lt;/p&gt;

&lt;p&gt;Performance result on &lt;a href=&quot;http://www.webpagetest.org/result/130104_NM_TYN/&quot;&gt;webpagetest&lt;/a&gt;&lt;/p&gt;

&lt;h5 id=&quot;upload-to-s3&quot;&gt;Upload to s3&lt;/h5&gt;

&lt;p&gt;To deploy to Amazon S3 the following s3cmd line can be used:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;s3cmd sync --dry-run --skip-existing --delete-removed ~/Dropbox/weblog-andrej/site-src/_site/ s3://&amp;lt;bucket name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

</content>
    </entry>
    
    <entry>
        <title>Remote debuggen van mobiele applicaties</title>
        <link href="http://www.andrejkoelewijn.com/blog/2012/12/05/remote-debuggen-van-mobiele-web-applicaties/" type="text/html" rel="alternate"/>
        <published>2012-12-05T00:00:00+01:00</published>
        <updated>2012-12-05T00:00:00+01:00</updated>
        <id>http://www.andrejkoelewijn.com/blog/2012/12/05/remote-debuggen-van-mobiele-web-applicaties</id>
        <author>
          <name>Andrej Koelewijn</name>
          <uri>http://www.andrejkoelewijn.com/</uri>
        </author>
        <content type="html">&lt;p&gt;Ik kwam vanochtend op &lt;a href=&quot;https://plus.google.com/u/0/115552999294763744109/posts/PssvQU4qtwc&quot;&gt;Google+&lt;/a&gt; een interessante &lt;a href=&quot;http://margaretleibovic.com/talks/mozilla/mobile.html#1&quot;&gt;presentatie van Magaret Leibovic&lt;/a&gt; tegen waarin ze onder andere de tools in firefox bespreekt die je kunt gebruiken voor het debuggen van web applicaties op een smartphone.&lt;/p&gt;

&lt;p&gt;Safari biedt &lt;a href=&quot;http://moduscreate.com/enable-remote-web-inspector-in-ios-6/&quot;&gt;vergelijkbare tooling&lt;/a&gt; om webapplicaties op een iPad of iPhone te debuggen. Deze heb ik recent gebruikt, en ik moet zeggen, dat werkt heel aardig. Tooling is vrij compleet: er is ondersteuning voor javascript debugging, je kunt zien welke resources van het netwerk gedownload worden, de timing, wat er in de appcache is opgeslagen, etc. Grootste nadeel is dat je nu ook voor het ontwikkelen van webapplicaties Mac OSX nodig hebt, aangezien dit alleen in safari ondersteund wordt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2012/12/safari-remote-debugging.png&quot; alt=&quot;Safari Remote Debugging&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Firefox biedt vergelijkbare functionaliteit, maar nog lang niet zo uitgebreid. In Firefox 18 zit een &lt;a href=&quot;https://hacks.mozilla.org/2012/08/remote-debugging-on-firefox-for-android/&quot;&gt;remote javascript debugger&lt;/a&gt;, in Firefox 19 komt ook ondersteuning voor &lt;a href=&quot;http://starkravingfinkle.org/blog/2012/10/firefox-for-android-remote-web-console-is-here/&quot;&gt;remote web logging&lt;/a&gt; (console.log). De overige tooling lijkt nog afwezig. &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2012/12/firefox-remote-debugger.png&quot; alt=&quot;Firefox remote debugger&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ook chrome biedt ondertussen ondersteuning voor het &lt;a href=&quot;https://developers.google.com/chrome/mobile/docs/debugging&quot;&gt;remote debuggen van mobiele web applicaties&lt;/a&gt;. Helaas alleen op Android. Er is wel een chrome voor iOS, maar deze heeft geen remote debugging ondersteuning. De tooling van Chrome voor debuggen is wel een stuk completer dan van Firefox, zoals je in onderstaande screenshots kunt zien.&lt;/p&gt;

&lt;p&gt;Javascript debugging:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2012/12/chrome-remote-debugging.png&quot; alt=&quot;Chrome remote debugging&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Debuggen van netwerk verkeer:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2012/12/chrome-remote-network.png&quot; alt=&quot;Chrome remote network&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Resources view is handig als je wilt zien of offline caching mbv appcache werkt:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2012/12/chrome-remote-appcache.png&quot; alt=&quot;Chrome remote appcache&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Helaas is er dus nog geen goede tooling die overal werkt, maar Safari en Chrome lopen duidelijk voor op Firefox. Hopelijk komt daar snel verandering in.&lt;/p&gt;

</content>
    </entry>
    
</feed>

