<?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>JTeam Blog</title>
	<atom:link href="http://blog.jteam.nl/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.jteam.nl</link>
	<description>Keep updated on what we&#039;re doing!</description>
	<lastBuildDate>Wed, 01 Sep 2010 17:48:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Social sites, lessons learned</title>
		<link>http://blog.jteam.nl/2010/09/01/social-sites-lessons-learned/</link>
		<comments>http://blog.jteam.nl/2010/09/01/social-sites-lessons-learned/#comments</comments>
		<pubDate>Wed, 01 Sep 2010 08:57:14 +0000</pubDate>
		<dc:creator>Erik van Oosten</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Best Practices]]></category>
		<category><![CDATA[Perpetual Beta]]></category>
		<category><![CDATA[Social Sites]]></category>

		<guid isPermaLink="false">http://blog.jteam.nl/?p=1757</guid>
		<description><![CDATA[As JTeam is a good match for companies starting a social website, we have had the pleasure of building a couple in the past years. This article summarizes some of the lessons we learned. If you plan to start a social website (any other new site for that matter), take notice. Contents Go live immediately [...]]]></description>
			<content:encoded><![CDATA[<p>As JTeam is a good match for companies starting a social website, we have had the pleasure of building a couple in the past years. This article summarizes some of the lessons we learned. If you plan to start a social website (any other new site for that matter), take notice.</p>
<p><strong>Contents</strong></p>
<ul>
<li>Go live immediately</li>
<li>Focus on as little use cases as possible</li>
<li>Be viral</li>
<li>Forget pixel perfect, improve as you go</li>
<li>Choose the right technology</li>
</ul>
<p><span id="more-1757"></span></p>
<h3>Go live immediately</h3>
<p>You&#8217;ll need to go live as soon as possible. Each and every one of our clients with a social website thought they knew what their clients wanted. They were all wrong (initially). Of course not totally-of-the-track-wrong, but still wrong enough to have wasted valuable time and money. If you go live immediately, you and your users immediately gain insight into how the site works and what you need to do first to improve it. </p>
<p><strong>Lesson learned:</strong> You will only know which use cases are really important if your site is being used by real users and they start to provide you with feedback.</p>
<h3>Focus on as little use cases as possible (a variation on the previous)</h3>
<p>Again, in <em>all</em> of the social websites JTeam has build, our client had a long list of use cases that needed implementing. This obviously translated into an even longer list of features. However, not all of those features were used or even understood by the users. In the majority of sites, we even had to take out features again later.</p>
<p>In combination with the previous lesson learned, the idea of <a href="http://en.wikipedia.org/wiki/Perpetual_beta">Perpetual Beta</a> can be used for developing your site. This basically means that you release your site early and do quick releases to enhance and extend the site gradually over time. </p>
<p><strong>Lesson learned:</strong> You will only know how your site will be used when it is actually being used. At this time it will become apparent what features are useful, which are not. Adding features upfront is not only wasteful, it is counter productive.</p>
<h3>Be viral</h3>
<p>A common misconception is that a social website needs users. Wrong! You need lots and lots of users, not a thousand, but multiple thousands at least. But how do you get them? The best way is to go viral; you need your users to attract even more users. There are several ways to achieve this. One old fashioned way is some kind of incentive program (expressed as status or plain money). Another status raiser for your site might be a cool mobile application (e.g. iPhone/iPad, Android) that extends the site. Another, probably much much more interesting option, is to build widgets for other social websites like Hyves, Facebook and LinkedIn. I would even go so far as to build the site to serve this user group first. Also using mechanisms to make it easy for users of those other social websites to start using your site will help in adoption. An example of this is using Facebook Connect to allow users to log into your site by using their Facebook credentials.</p>
<p><strong>Lesson learned:</strong> Often, features alone are not enough, create attention by hooking into other (big) social sites.</p>
<h3>Forget pixel perfect, improve as you go</h3>
<p>The first users are not so critical. They like it if they see a continuous stream of small improvements. It makes them feel at home. This is the attitude you like to foster. Forget IE 6 as well, your target group is not likely to use this ancient browser anyway.<br />
Often, our clients focus on pixels rather than functionality and don&#8217;t want to release until each and every page is pixel perfect. This leads to a lot of time (and money) being spent on layout rather than functionality.</p>
<p><strong>Lesson learned:</strong> Don&#8217;t stop a release because there is a small layout problem. Fix it in the next release.</p>
<h3>Choose the right technology</h3>
<p>You will need technology that is easy to use now, but that won&#8217;t bog you down as your site grows. Large site require dis-proportionally more money then small sites. In particular we noticed that relational databases and transaction script architectures are in the way for the type of changes that are required for growing a site. We learned that scalable technologies like Solr (search) and Axon (event based architecture) are better suited for this.</p>
<p>Besides choosing technologies that scale well and are future proof, obviously you also want to make the right choice for technologies that actually do what you want it to do&#8230; Especially when you rely fully on a technology partner, make sure that you validate their choices. We have seen numerous cases where our clients came to us with an already developed site that simply used the wrong technologies. This even goes as far as a frontend technology choice for a website that wasn&#8217;t indexable by Google, while being findable in Google was of the utmost importance from a business perspective. Each technology has a home ground where its suitable and making the wrong choice there can be disaster.  </p>
<p><strong>Lesson learned:</strong> Making the right technology choices is essential to ensure scalability and maintainability, but also essential to getting a system that serves your business. Make sure you have a solid technology partner with a track record of choosing the right technologies and ensure you have (or hire) the expertise to validate their choices.</p>
<h3>Conclusion</h3>
<p>The above lessons learned will help you be more successful in developing your social website if you keep them in mind. Obviously, JTeam can help in advising you, even before you start the implementation. If you are thinking about a social business concept, feel free to <a href="http://www.jteam.nl/contact.html">contact us</a>.  </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jteam.nl/2010/09/01/social-sites-lessons-learned/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Monitoring Hippo Connection pool using jmx and groovy</title>
		<link>http://blog.jteam.nl/2010/08/19/monitoring-hippo-connection-pool-using-jmx-and-groovy/</link>
		<comments>http://blog.jteam.nl/2010/08/19/monitoring-hippo-connection-pool-using-jmx-and-groovy/#comments</comments>
		<pubDate>Thu, 19 Aug 2010 10:10:32 +0000</pubDate>
		<dc:creator>Jettro Coenradie</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[Hippo]]></category>
		<category><![CDATA[JMX]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://blog.jteam.nl/?p=2442</guid>
		<description><![CDATA[For a project we are using Hippo to manage our content. We have a few components that interact with the repository using the connection pool as provided by hippo. I have modified the connection pool to increase the amount of logs and I have added statistics to the pool which can be exposed using JMX. [...]]]></description>
			<content:encoded><![CDATA[<p>For a project we are using <a href="www.onehippo.org">Hippo</a> to manage our content. We have a few components that interact with the repository using the connection pool as provided by hippo. I have modified the connection pool to increase the amount of logs and I have added statistics to the pool which can be exposed using JMX. Our custom components use this altered connection pool, but I the site did not. Our site makes use of the Hippo Site Toolkit, and I want to have this monitoring available as well.</p>
<p>In this blogpost I will explain the changes I made to the connection pool. After that I&#8217;ll show what to do to make this changed connection pool available to a site created with the HST and I&#8217;ll show a groovy script that reads the data from the remote servers using the JMX connection.</p>
<p><span id="more-2442"></span>
<p>I started writing about JMX, groovy and spring on my personal blog. I wrote about exposing jmx through spring. Adding groovy spring to the spring context and a bit more about JMX. Check these two posts:</p>
<p><a href="http://www.gridshore.nl/2010/06/02/using-jmx-within-a-spring-application/">﻿http://www.gridshore.nl/2010/06/02/using-jmx-within-a-spring-application/</a></p>
<p>﻿<a href="http://www.gridshore.nl/2010/06/20/exposing-jmx-through-jmxmp-and-reading-the-jmx-data-with-groovy/">http://www.gridshore.nl/2010/06/20/exposing-jmx-through-jmxmp-and-reading-the-jmx-data-with-groovy/</a></p>
<p>In this blog post I&#8217;ll give more details to use this in a Hippo environment.</p>
<h2>Changes to the connection pool</h2>
<p>Hippo provides the <strong>hst-session-pool</strong> and the <strong>﻿﻿hippo-ecm-repository-connector</strong>. The names a re descriptive enough to understand the goals for the two components. In this blog post I am particularly interested in the hst-session-pool. If you are creating an HST website, the spring configuration is configured in the <strong>SpringComponentManager-jcr.xml</strong>. This is not handled the same as a normal spring web application. But Hippo provides a mechanism to create your own instance of this file and overload the one that is provided by Hippo. More on this later.</p>
<p>For now let us have a look at the class we have created to replace the ﻿<strong>org.hippoecm.hst.core.jcr.pool.BasicPoolingRepository</strong> as provided by Hippo. I am not going over all the methods. I will give you an idea of the changes I made. First an image with the components that are involved.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://blog.jteam.nl/wp-content/uploads/2010/08/overview-connection-monitoring.png" border="0" alt="overview-connection-monitoring.png" width="538" height="249" /></p>
<p>The blue block is a changed Hippo class, the yellow ones are extensions to support monitoring. PoolingStatistics is used to track statistics like the amount of sessions that are obtained and the amount of sessions that are returned. The BasicPoolingRepositoryWihtLogging uses this statistics object to store this data and exposes it so other can read the data. The PoolingRepositoryMonitor reads the required data from the other two components and exposes this using JMX.</p>
<p>To get an idea of the type of changes I made, have a look at the following code block. The first method is the one from hippo, the second the one that I changed. Look at the use of the statistics object and the logging.</p>
<pre class="brush: java;">
    public Session login() throws LoginException, RepositoryException {
        Session session = null;

        try {
            session = (Session) this.sessionPool.borrowObject();
        } catch (NoSuchElementException e) {
            throw new NoAvailableSessionException(&quot;No session is available now. Probably the session pool was exhasuted.&quot;);
        } catch (Exception e) {
            throw new LoginException(&quot;Failed to borrow session from the pool.&quot;, e);
        }

        return session;
    }

    public Session login() throws LoginException, RepositoryException {
        log.debug(&quot;Request session by doing a login.&quot;);
        try {
            Session session = (Session) this.sessionPool.borrowObject();
            log.debug(&quot;Return a session with object id {} from the pool after a login&quot;, session.hashCode());
            statistics.sessionObtained();
            return session;
        } catch (NoSuchElementException e) {
            log.debug(&quot;Problem obtaining session from the pool&quot;, e);
            throw new NoAvailableSessionException(&quot;No session is available now. Probably the session pool was exhausted.&quot;);
        } catch (Exception e) {
            throw new LoginException(&quot;Failed to borrow session from the pool.&quot;, e);
        }
    }
</pre>
<p>Now we have the altered connection pool class, we have the class that can be exposed through JMX using Spring. Next step is to tell the HST to use this class. Look for the file SpringComponentManager-jcr.xml, make a copy and put this copy in the folder (taken that you use maven to build your project) <strong>src/main/resources/META-INF/hst-assembly/overrides</strong>. Look for all usages of <strong>org.hippoecm.hst.core.jcr.pool.BasicPoolingRepository</strong> and replace these with the name of your own implementation. At the time of writing there are 5 different repositories in use by the hst. Next up is to initialize the PoolingReposityMonitor beans. We create a bean for each repository bean, so we have 5 monitors. The final part in the spring configuration is to expose the jmx beans using the mBeanServer. Spring provides some beans for that as well. The following code block show the most important beans.</p>
<pre class="brush: xml;">
    &lt;context:mbean-server/&gt;
    &lt;context:mbean-export registration=&quot;replaceExisting&quot; server=&quot;mbeanServer&quot;/&gt;
    &lt;bean id=&quot;jmxServerConnector&quot; class=&quot;org.springframework.jmx.support.ConnectorServerFactoryBean&quot;&gt;
        &lt;property name=&quot;threaded&quot; value=&quot;true&quot;/&gt;
        &lt;property name=&quot;daemon&quot; value=&quot;true&quot;/&gt;
        &lt;property name=&quot;server&quot; ref=&quot;mbeanServer&quot;/&gt;
        &lt;property name=&quot;serviceUrl&quot; value=&quot;${jmx.serviceurl}&quot;/&gt;
    &lt;/bean&gt;
    &lt;bean id=&quot;defaultJmxRepository&quot; class=&quot;package.name.of.monitor.PoolingRepositoryMonitor&quot;&gt;
        &lt;constructor-arg ref=&quot;defaultPoolingRepository&quot; index=&quot;0&quot;/&gt;
        &lt;constructor-arg value=&quot;readonly&quot; index=&quot;1&quot;/&gt;
    &lt;/bean&gt;
    &lt;bean id=&quot;previewJmxRepository&quot; class=&quot;package.name.of.monitor.PoolingRepositoryMonitor&quot;&gt;
        &lt;constructor-arg ref=&quot;previewPoolingController&quot; index=&quot;0&quot;/&gt;
        &lt;constructor-arg value=&quot;preview&quot; index=&quot;1&quot;/&gt;
    &lt;/bean&gt;
    &lt;bean id=&quot;hstConfigJmxRepository&quot; class=&quot;package.name.of.monitor.PoolingRepositoryMonitor&quot;&gt;
        &lt;constructor-arg ref=&quot;hstConfigReaderPoolingRepository&quot; index=&quot;0&quot;/&gt;
        &lt;constructor-arg value=&quot;hstConfig&quot; index=&quot;1&quot;/&gt;
    &lt;/bean&gt;
    &lt;bean id=&quot;writeableJmxRepository&quot; class=&quot;package.name.of.monitor.PoolingRepositoryMonitor&quot;&gt;
        &lt;constructor-arg ref=&quot;writeablePoolingRepository&quot; index=&quot;0&quot;/&gt;
        &lt;constructor-arg value=&quot;writeable&quot; index=&quot;1&quot;/&gt;
    &lt;/bean&gt;
    &lt;bean id=&quot;binariesJmxRepository&quot; class=&quot;package.name.of.monitor.PoolingRepositoryMonitor&quot;&gt;
        &lt;constructor-arg ref=&quot;binaryPoolingRepository&quot; index=&quot;0&quot;/&gt;
        &lt;constructor-arg value=&quot;binaries&quot; index=&quot;1&quot;/&gt;
    &lt;/bean&gt;
</pre>
<p>It is now possible to use a jmx client like jconsole to have a look at the beans. But that is not what I want. I want to connect remote using groovy and I want a nice page that show the basic information. The hst has the possibility to using spring mvc within the hst. I am not going into details on how to do this. Woonsan has written an excellent blog post that explains how to do this.</p>
<p>﻿<a href="http://blogs.onehippo.org/woonsan/2009/06/spring_web_mvc_framework_suppo_1.html">http://blogs.onehippo.org/woonsan/2009/06/spring_web_mvc_framework_suppo_1.html</a></p>
<p>I have configured a controller that has a dependency on a groovy bean. The groovy bean created a few instanced of a class MonitorGroup that just contains a title and a map of parameters. The first code block shows the spring configuration. The second code block shows the groovy part of reading the jmx beans for the hippo session pools.</p>
<pre class="brush: xml;">
    &lt;bean class=&quot;nl.rijksoverheid.monitoring.JmxController&quot;&gt;
        &lt;constructor-arg ref=&quot;jmxMonitor&quot;/&gt;
    &lt;/bean&gt;

    &lt;lang:groovy script-source=&quot;classpath:groovy/JmxMonitor.groovy&quot; id=&quot;jmxMonitor&quot;&gt;
        &lt;lang:property name=&quot;mbeanServer&quot; ref=&quot;mbeanServer&quot;/&gt;
    &lt;/lang:groovy&gt;
</pre>
<pre class="brush: java;">
    private MonitorGroup createHippoConnectionPoolMonitorGroup() {
        def hippoPoolingQuery = new ObjectName('package.name.of.monitor:*')

        MonitorGroup monitorGroup = new MonitorGroup() {

            List&lt;String&gt; getColumns() {
                return [&quot;Name&quot;, &quot;Type&quot;,&quot;Active&quot;, &quot;Idle&quot;, &quot;Obtained&quot;, &quot;Returned&quot;, &quot;Initial size&quot;, &quot;Max active&quot;, &quot;Max Idle&quot;, &quot;Min Idle&quot;];
            }

            List&lt;Object&gt; getValues() {
                String[] connectionPools = mbeanServer.queryNames(hippoPoolingQuery, null)
                def connectionModules = connectionPools.findAll { name -&gt;
                    name.contains('type=PoolingRepositoryMonitor')
                }.collect { new GroovyMBean(mbeanServer, it) }

                return connectionModules.collect {[
                            it.name().getKeyProperty(&quot;name&quot;),
                            it.PoolType,
                            it.NumSessionsActive,
                            it.NumSessionsIdle,
                            it.NumSessionsObtained,
                            it.NumSessionsReturned,
                            it.InitialSize,
                            it.MaxActive,
                            it.MaxIdle,
                            it.MinIdle
                ]}
            }

            String getName() {
                return &quot;Hippo connection pools&quot;;
            }
        }
        return monitorGroup
    }
</pre>
<p>Now we need to handle an incoming request, so we need a controller. And in the end we want to show the data on the screen. That is done using a jsp. The following two code blocks show the controller and the important part of the jsp.</p>
<pre class="brush: java;">
@Controller
public class JmxController {
    private GenericMonitor monitor;

    @Autowired
    public JmxController(GenericMonitor monitor) {
        this.monitor = monitor;
    }

    @RequestMapping(value = &quot;/spring/jmx.do&quot;, method = RequestMethod.GET)
    public String adminView(ModelMap modelMap) {
        List&lt;MonitorGroup&gt; list = monitor.monitorGroups();
        modelMap.addAttribute(&quot;groups&quot;, list);

        return &quot;admin/jmx&quot;;
    }
}
</pre>
<pre class="brush: xml;">
&lt;c:forEach var=&quot;group&quot; items=&quot;${groups}&quot;&gt;
    &lt;div class=&quot;block-error&quot;&gt;
        &lt;h2&gt;&lt;c:out value=&quot;${group.name}&quot;/&gt;&lt;/h2&gt;
        &lt;table&gt;
            &lt;tr&gt;
                &lt;c:forEach var=&quot;columnHeader&quot; items=&quot;${group.columns}&quot;&gt;
                    &lt;th&gt;&lt;c:out value=&quot;${columnHeader}&quot;/&gt;&lt;/th&gt;
                &lt;/c:forEach&gt;
            &lt;/tr&gt;
            &lt;c:forEach var=&quot;valueRow&quot; items=&quot;${group.values}&quot;&gt;
                &lt;tr&gt;
                    &lt;c:forEach var=&quot;valueItem&quot; items=&quot;${valueRow}&quot;&gt;
                        &lt;td&gt;&lt;c:out value=&quot;${valueItem}&quot;/&gt;&lt;/td&gt;
                    &lt;/c:forEach&gt;
                &lt;/tr&gt;
            &lt;/c:forEach&gt;
        &lt;/table&gt;
    &lt;/div&gt;
&lt;/c:forEach&gt;
</pre>
<p>Of course you are now very curious what we have, well have a look at the following screendump.</p>
<p><img style="display:block; margin-left:auto; margin-right:auto;" src="http://blog.jteam.nl/wp-content/uploads/2010/08/Screen-shot-2010-08-19-at-12.08.16.png" alt="Screen shot 2010-08-19 at 12.08.16.png" border="0" width="500" height="588" /></p>
<p>Still here? Want more? Ok than we will have a look at the last part of this blog post. The groovy script to read the jmx data from a remote machine. The server side is fine, we can use that now. We have used spring to expose jmx beans over jmxmp. The implementation looks a lot like the JmxMonitor bean that has been discussed before. It should be easy to understand. The code block shows the implementation and after that the output.</p>
<pre class="brush: java;">
def hippoPoolingQuery = new ObjectName('nl.rijksoverheid.importer.repository.pooling:*')
String[] connectionPools = server.queryNames(hippoPoolingQuery, null)

def connectionModules = connectionPools.findAll { name -&gt;
    name.contains('type=PoolingRepositoryMonitor')
}.collect { new GroovyMBean(server, it) }

println &quot;**Found $connectionModules.size hippo connection pools&quot;
if (connectionModules.size) println &quot;Name                     Type      Active Idle Obtained Returned Max Active Max Idle Min Idle Initial Created Destroyed Activated Passivated&quot;
connectionModules.each {m-&gt;
    def nameOfEqualLength = m.name().getKeyProperty(&quot;name&quot;)
    def nameLength = nameOfEqualLength.size()
    if (nameLength &lt; 50) {
        nameOfEqualLength = nameOfEqualLength.padRight (25)
    }
    print m.name().getKeyProperty(&quot;name&quot;).padRight(25)
    print m.PoolType.padRight(12)
    print &quot;$m.NumSessionsActive&quot;.padRight(7)
    print &quot;$m.NumSessionsIdle&quot;.padRight(7)
    print &quot;$m.NumSessionsObtained&quot;.padRight(7)
    print &quot;$m.NumSessionsReturned&quot;.padRight(10)
    print &quot;&quot;.padRight(37)
    print &quot;$m.MaxActive&quot;.padRight(10)
    print &quot;$m.MaxIdle&quot;.padRight(10)
    print &quot;$m.MinIdle&quot;.padRight(10)
    print &quot;$m.InitialSize&quot;.padRight(12)
    print &quot;$m.NumItemsCreated&quot;.padRight(10)
    print &quot;$m.NumItemsDestroyed&quot;.padRight(10)
    print &quot;$m.NumItemsActivated&quot;.padRight(10)
    print &quot;$m.NumItemsPassivated&quot;.padRight(12)
    print &quot;\n&quot;
}
</pre>
<pre class="brush: plain;">
**Found 5 hippo connection pools
Name                     Type      Active Idle Obtained Returned Max Active Max Idle Min Idle Initial Created Destroyed Activated Passivated
writeableJmxRepository   writeable   0      0      0      0         100       5         0         0           0         0         0         0
binariesJmxRepository    binaries    0      0      0      0         100       10        0         0           0         0         0         0
hstConfigJmxRepository   hstConfig   1      1      3      2         25        5         0         0           2         0         3         2
defaultJmxRepository     readonly    0      0      0      0         100       25        0         0           0         0         0         0
previewJmxRepository     preview     0      0      0      0         100       5         0         0           0         0         0         0           
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.jteam.nl/2010/08/19/monitoring-hippo-connection-pool-using-jmx-and-groovy/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Running ActiveMQ using Spring</title>
		<link>http://blog.jteam.nl/2010/08/12/running-activemq-using-spring/</link>
		<comments>http://blog.jteam.nl/2010/08/12/running-activemq-using-spring/#comments</comments>
		<pubDate>Thu, 12 Aug 2010 12:31:45 +0000</pubDate>
		<dc:creator>Diego Castorina</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[ActiveMQ]]></category>
		<category><![CDATA[JMS]]></category>
		<category><![CDATA[Spring Framework]]></category>

		<guid isPermaLink="false">http://blog.jteam.nl/?p=2413</guid>
		<description><![CDATA[Apache ActiveMQ is an open source messaging framework. The ActiveMQ web site is not really clear on how to integrate it with the Spring framework. Therefore, I decided to write this post to explain how to use ActiveMQ in combination with Spring and clarify some points. The good news is that you can run JMS [...]]]></description>
			<content:encoded><![CDATA[<p>Apache ActiveMQ is an open source messaging framework. The ActiveMQ web site is not really clear on how to integrate it with the Spring framework. Therefore, I decided to write this post to explain how to use ActiveMQ in combination with Spring and clarify some points.<br />
The good news is that you can run JMS inside a servlet container (e.g. Apache Tomcat) without the need for a JCA adapter. This means you do not need Jencks or something similar.</p>
<p><span id="more-2413"></span></p>
<div style="background-color: #4B08A1; color: white; font-weight: bold; padding: 10px; margin: 10px">
Note:<br />
This is a repost of a blog item that was originally posted in the Func knowledge base by Diego Castorina on January 29, 2010.
</div>
<p>To get started, you can embed the configuration of a complete running environment in a Spring configuration file. Here is the example we&#8217;ll use for the remainder of this blog post:</p>
<pre class="brush: xml;">
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
       xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
       xmlns:amq=&quot;http://activemq.apache.org/schema/core&quot;
       xmlns:jms=&quot;http://www.springframework.org/schema/jms&quot;
       xsi:schemaLocation=&quot;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-2.5.xsd&quot;&gt;
  &lt;amq:broker brokername=&quot;test-broker&quot; start=&quot;true&quot;&gt;
    &lt;amq:persistenceAdapter&gt;
      &lt;amq:amqPersistenceAdapter directory=&quot;/opt/activemq&quot; maxFileLength=&quot;32mb&quot;/&gt;
    &lt;/amq:persistenceAdapter&gt;
    &lt;amq:transportconnectors&gt;
      &lt;amq:transportconnector uri=&quot;tcp://localhost:7171&quot;/&gt;
    &lt;/amq:transportconnectors&gt;
  &lt;/amq:broker&gt;
  &lt;amq:connectionFactory id=&quot;amqConnectionFactory&quot;  brokerURL=&quot;vm://test-broker&quot;/&gt;
  &lt;bean class=&quot;org.springframework.jms.connection.CachingConnectionFactory&quot; id=&quot;connectionFactory&quot;&gt;
    &lt;constructor-arg ref=&quot;amqConnectionFactory&quot;/&gt;
    &lt;property name=&quot;sessionCacheSize&quot; value=&quot;100&quot;/&gt;
  &lt;/bean&gt;
  &lt;amq:queue physicalName=&quot;testQueue&quot; /&gt;
  &lt;bean class=&quot;org.springframework.jms.core.JmsTemplate&quot;  id=&quot;jmsTemplate&quot;&gt;
    &lt;constructor-arg ref=&quot;connectionFactory&quot;/&gt;
  &lt;/bean&gt;
  &lt;bean class=&quot;packageName.ClassName&quot; id=&quot;queueProducer&quot;&gt;
    &lt;property name=&quot;jmsTemplate&quot; ref=&quot;jmsTemplate&quot;/&gt;
    &lt;property name=&quot;queueName&quot; value=&quot;testQueue&quot;/&gt;
  &lt;/bean&gt;
  &lt;bean class=&quot;packageName.ClassName2&quot; id=&quot;queueListener&quot;/&gt;
  &lt;jms:listener-container concurrency=&quot;10&quot; connectionfactory=&quot;connectionFactory&quot;&gt;
    &lt;jms:listener destination=&quot;testQueue&quot; ref=&quot;queueListener&quot;/&gt;
  &lt;/jms:listener-container&gt;
&lt;/beans&gt;
</pre>
<p>That&#8217;s a lot of configuration, but let&#8217;s analyze each one:</p>
<pre class="brush: xml;">
&lt;amq:broker brokername=&quot;test-broker&quot; start=&quot;true&quot;&gt;
  &lt;amq:persistenceAdapter&gt;
    &lt;amq:amqPersistenceAdapter directory=&quot;/opt/activemq&quot; maxFileLength=&quot;32mb&quot;/&gt;
  &lt;/amq:persistenceAdapter&gt;
  &lt;amq:transportconnectors&gt;
    &lt;amq:transportconnector uri=&quot;tcp://localhost:7171&quot;/&gt;
  &lt;/amq:transportconnectors&gt;
&lt;/amq:broker&gt;
</pre>
<p>This is the definition for an embedded JMS broker, called <code>test-broker</code> which listens on port 7171 using the tcp protocol and which persist data using the default AMQ Message Store in the <code>/opt/activemq</code> directory.</p>
<pre class="brush: xml;">
&lt;amq:connectionFactory id=&quot;amqConnectionFactory&quot; brokerURL=&quot;vm://test-broker&quot;/&gt;
</pre>
<p>The definition of the JMS connection factory which connects to the broker using a VM transport. In this way the communication is made at the JVM level, thus avoiding network overhead.</p>
<pre class="brush: xml;">
&lt;amq:queue id=&quot;testQueue&quot; physicalname=&quot;TestQueue&quot;&gt;
</pre>
<p>Defines the queue that we are going to use.</p>
<pre class="brush: xml;">
&lt;bean class=&quot;org.springframework.jms.connection.CachingConnectionFactory&quot; id=&quot;connectionFactory&quot;&gt;
   &lt;constructor-arg ref=&quot;amqConnectionFactory&quot;/&gt;
   &lt;property name=&quot;sessionCacheSize&quot; value=&quot;100&quot;/&gt;
&lt;/bean&gt;
</pre>
<p>This is the connection factory we are really going to use in our application. It caches connections, sessions and even the <code>MessageProducer</code>. It is important to set the value of the <code>sessionCacheSize</code> property since the default value is 1.</p>
<pre class="brush: xml;">
&lt;bean class=&quot;org.springframework.jms.core.JmsTemplate&quot; id=&quot;jmsTemplate&quot;&gt;
   &lt;constructor-arg ref=&quot;connectionFactory&quot;/&gt;
&lt;/bean&gt;
</pre>
<p>For those who know the Spring support for JDBC and Hibernate, the <code>JmsTemplate</code> class should sound familiar since it has a very similar design to the <code>JdbcTemplate</code> and <code>HibernateTemplate</code> class.<br />
It hides most of the JMS-related low-level details (e.g. obtaining a session or handling acknowledgments). By default session are not transactional and auto-acknowledged.<br />
The <code>connectionFactory</code> is passed as a property to the constructor.<br />
One of its most important method on the <code>JmsTemplate</code> is <code>send(String destinationName, MessageCreator messageCreator)</code>. The <code>MessageCreator</code> is an interface defined by Spring having only the <code>createMessage(Session session)</code> method. Its output is the JMS message that will be sent to <code>destinationName</code>.</p>
<pre class="brush: xml;">
&lt;bean class=&quot;packageName.ClassName&quot; id=&quot;queueProducer&quot;&gt;
    &lt;property name=&quot;jmsTemplate&quot; ref=&quot;jmsTemplate&quot;&gt;&lt;/property&gt;
    &lt;property name=&quot;queueName&quot; value=&quot;testQueue&quot;&gt;&lt;/property&gt;
&lt;/bean&gt;
</pre>
<p>This, finally is an object that is defined within our application, the object that produces the message queue and sends messages to it through the specified <code>JmsTemplate</code>.</p>
<pre class="brush: xml;">
&lt;bean class=&quot;packageName.ClassName2&quot; id=&quot;queueListener&quot;/&gt;
</pre>
<p>The bean definition that makes up the consumer of our message queue. It needs to implement the <code>javax.jms.MessageListener</code> interface (or some Spring specific interface like <code>SessionAwareMessageListener</code>).<br />
In Spring terms it is a Message Driven Pojo, the difference with a standard Message Driven Bean is that it does not need to run in an EJB container.</p>
<pre class="brush: xml;">
&lt;jms:listener-container concurrency=&quot;1&quot; connection-factory=&quot;connectionFactory&quot;&gt;
    &lt;jms:listener destination=&quot;AggregateQueue&quot; ref=&quot;queueListener&quot;&gt;&lt;/jms:listener&gt;
&lt;/jms:listener-container&gt;
</pre>
<p>This is the bean who makes the magic happen: it registers itself as a listener for all the queues and executes the callback on the listener as a message is received in an asynchronous way using a Spring <code>TaskExecutor</code>. The concurrency attribute defines how many <code>MessageConsumer</code> instances will be created for each listener. If you use a value &gt; 1 remember to set the <code>prefetchLimit</code> to 1 in order to avoid undelivered messages to the consumers.</p>
<p>Have fun <img src='http://blog.jteam.nl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jteam.nl/2010/08/12/running-activemq-using-spring/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Axon Framework 0.6 released</title>
		<link>http://blog.jteam.nl/2010/08/08/axon-framework-0-6-released/</link>
		<comments>http://blog.jteam.nl/2010/08/08/axon-framework-0-6-released/#comments</comments>
		<pubDate>Sun, 08 Aug 2010 17:54:06 +0000</pubDate>
		<dc:creator>Allard Buijze</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Axon Framework]]></category>
		<category><![CDATA[CQRS]]></category>

		<guid isPermaLink="false">http://blog.jteam.nl/2010/08/08/axon-framework-0-6-released/</guid>
		<description><![CDATA[Today, I released version 0.6 of the Axon Framework. 0.6 has many new features and is another step towards full production readiness. There is still some work to do, but first, let’s take a look at what has changed… Test fixtures are now part of the axon-test module. These fixtures allow you to test your [...]]]></description>
			<content:encoded><![CDATA[<p>Today, I released version 0.6 of the Axon Framework. 0.6 has many new features and is another step towards full production readiness. There is still some work to do, but first, let’s take a look at what has changed…</p>
<p> <span id="more-2410"></span>
<p>Test fixtures are now part of the axon-test module. These fixtures allow you to test your command handling logic based on events and commands. You define these tests in a given-when-then style: given these past events, when I execute this command, I expect these events to occur. </p>
<p>The <tt>CommandBus</tt> interface now allows for asynchronous command dispatching. Instead of using a return value, a Callback can be given to the command bus if you wish to be notified of the result of command execution. </p>
<p>The repositories make use of a <tt>UnitOfWork</tt> instance, which keeps track of changed aggregates and generated events. Instead of saving each aggregate separately, the <tt>UnitOfWork</tt> can be committed, causing changed aggregates to be stored, and events to be dispatched. With the new <tt>SimpleUnitOfWorkInterceptor</tt> or the <tt>SpringTransactionalInterceptor</tt>, it is no longer necessary to call <tt>repository.save()</tt>. In fact, you are discouraged from doing so. </p>
<p>Repositories are now capable of detecting conflicting modifications. When loading an aggregate, you may pass in the expected version of the aggregate. An exception is raised if that version does not match the actual version. </p>
<p>Event sourcing repositories allow for a more advanced way of detecting conflicts. Sometimes, not all concurrent modification are in conflict with each other. One user may very well change the shipping address of an order, while another user is adding items. Other modifications, however, are clearly conflicting, such as one user marking an order as shipped, and another one adding a product. For this purpose, you can register a <tt>ConflictResolver</tt> with the repository. This conflict resolver can, based on unseen and newly applied events, decide whether the changes made by the second user are accepted. </p>
<p>Axon now provides a mechanism to trigger snapshot creation based on the number of events needed to load to reconstitute an aggregate. When the number of events exceeds a given threshold, a snapshot is created and stored in the Event Store. </p>
<p>The <tt>SimpleCommandBus</tt> and <tt>SimpleEventBus</tt> now expose statistics over JMX. Although currently quite limited, the statistics will be improved in the coming versions. </p>
<p>All of these features help making applications with CQRS-based architectures even easier. But we’re not there yet. The coming months, we will try to make it even easier with features like Event versioning, support for aggregates with multiple entities, and whatever comes to mind in Axon’s growing community.</p>
<p>For more information about the Axon Framework, see <a href="http://www.axonframework.org">www.axonframework.org</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jteam.nl/2010/08/08/axon-framework-0-6-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Connecting to FTP server with Spring Integration</title>
		<link>http://blog.jteam.nl/2010/07/21/connecting-to-ftp-server-with-spring-integration/</link>
		<comments>http://blog.jteam.nl/2010/07/21/connecting-to-ftp-server-with-spring-integration/#comments</comments>
		<pubDate>Wed, 21 Jul 2010 13:07:50 +0000</pubDate>
		<dc:creator>Roberto van der Linden</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[FTP]]></category>
		<category><![CDATA[Spring Integration]]></category>

		<guid isPermaLink="false">http://blog.jteam.nl/?p=2389</guid>
		<description><![CDATA[For one of our project I needed to read zip files from a FTP server and import the content in a system. In this post I will explain how I have used the Spring Integration to connect with a FTP server and retrieve Zip files. FTP Client Factory As the FTP extension for Spring Integration [...]]]></description>
			<content:encoded><![CDATA[<p>For one of our project I needed to read zip files from a FTP server and import the content in a system. In this post I will explain how I have used the Spring Integration to connect with a FTP server and retrieve Zip files.<br />
<span id="more-2389"></span></p>
<h2>FTP Client Factory</h2>
<p>As the FTP extension for Spring Integration has no official release yet, I have used the latest build which can be found at the <a href="http://www.springsource.org/extensions/se-sia" target="_blank">Spring Integration Adapters site</a>.</p>
<p>The extension provides a client factory that allows you to connect with a client. The class I have used is the <a href="https://src.springframework.org/svn/se-sia/trunk/org.springframework.integration.ftp/src/main/java/org/springframework/integration/ftp/DefaultFTPClientFactory.java" target="_blank">DefaultFTPClientFactory</a> which implements the interface <a href="https://src.springframework.org/svn/se-sia/trunk/org.springframework.integration.ftp/src/main/java/org/springframework/integration/ftp/FTPClientFactory.java" target="_blank">FTPClientFactory</a>. </p>
<p>When you have copied these files to your own project, you can configure a client by using the following code:</p>
<pre>
<pre class="brush: xml;">
    &lt;bean id=&quot;defaultClient&quot; class=&quot;nl.jteam.importer.ftp.DefaultFTPClientFactory&quot;&gt;
        &lt;property value=&quot;${ftp.remotedir}&quot; name=&quot;remoteWorkingDirectory&quot;&gt;&lt;/property&gt;
        &lt;property value=&quot;${ftp.username}&quot; name=&quot;username&quot;&gt;&lt;/property&gt;
        &lt;property value=&quot;${ftp.password}&quot; name=&quot;password&quot;&gt;&lt;/property&gt;
        &lt;property value=&quot;${ftp.port}&quot; name=&quot;port&quot;&gt;&lt;/property&gt;
        &lt;property value=&quot;${ftp.host}&quot; name=&quot;host&quot;&gt;&lt;/property&gt;
    &lt;/bean&gt;
</pre>
</pre>
<h2>Reading the files</h2>
<p>Now that the client is configured, we can read the files from the FTP server. In the method <em>getFilesFromFTPClient()</em> we get a <a href="http://commons.apache.org/net/api/org/apache/commons/net/ftp/FTPClient.html" target="_blank">FTPClient</a> by calling the <em>getClient()</em> method on the client factory. The client API provides you with the possibility to retrieve, delete, rename or store files. The API offers a lot more, but I won&#8217;t discuss all the methods here. In our case we wanted to retrieve only zip files. As the client does not provide you the functionality to retrieve files from a specific extension, you have to do it yourself by, for example, checking the extension of each file.</p>
<p>Don’t forget to close the connection with the FTP client once you are done with handling files.</p>
<p>Because we want use Spring Integration to send the files to the class that handles the zip files, we create a <a href="http://static.springsource.org/spring-integration/reference/htmlsingle/spring-integration-reference.html#overview-components" target="_blank">Message</a> with the list of zip files. </p>
<p>The (partial) code of the FTPInboundAdapter class:</p>
<pre>
<pre class="brush: java;">
    public FTPInboundAdapter(FTPClientFactory clientFactory, String localTmpDirName) throws IOException {
        Assert.notNull(localTmpDirName, &quot;The directory name to write the files to can not be null&quot;);
        this.clientFactory = clientFactory;
        localDirectory = ImportUtils.ensureTempDirExists(localTmpDirName);
    }

    public Message&lt;list&gt;&lt;file&gt;&amp;gt; getFilesFromFTPClient() {
        FTPClient client = null;
        try {
            client = clientFactory.getClient();

            List&lt;file&gt; localZipFiles = retrieveRemoteZipFiles(client);

            return MessageBuilder.withPayload(localZipFiles).build();
        } catch (IOException e) {
            throw new MessagingException(&quot;Problem occurred while trying to retrieve files.&quot;, e);
        } finally {
            closeFtpClient(client);
        }
    }

    private void closeFtpClient(FTPClient client) {
        if (client != null &amp;amp;&amp;amp; client.isConnected()) {
            try {
                client.disconnect();
            } catch (IOException e) {
                logger.warn(&quot;Error occurred when disconnection FTP client&quot;, e);
            }
        }
    }
</pre>
</pre>
<p>The configuration code for the adapter:</p>
<pre>
<pre class="brush: xml;">
    &lt;bean id=&quot;ftpInboundAdapter&quot; class=&quot;nl.jteam.importer.ftp.FTPInboundAdapter&quot;&gt;
        &lt;constructor-arg ref=&quot;defaultClient&quot; /&gt;
        &lt;constructor-arg value=&quot;someLocalDirectory&quot; /&gt;
    &lt;/bean&gt;
</pre>
</pre>
<h2>Checking the FTP directory</h2>
<p>If you want Spring Integration to check the FTP server on a regular base for new files, you can wire up an inbound channel adapter with a cron expression like this:</p>
<pre>
<pre class="brush: xml;">
    &lt;si:inbound-channel-adapter id=&quot;zipInboundChannelAdapter&quot; ref=&quot;ftpInboundAdapter&quot; method=&quot;getFilesFromFTPClient&quot; channel=&quot;zipFilesChannel&quot;&gt;
        &lt;si:poller max-messages-per-poll=&quot;1&quot;&gt;
            &lt;si:cron-trigger expression=&quot;0 0/5 * ? * *&quot; /&gt;
        &lt;/si:poller&gt;
    &lt;/si:inbound-channel-adapter&gt;
</pre>
</pre>
<p>The channel attribute of the inbound channel adapter specifies the output channel. So in our case this will be the message with the list of zip files that is put onto this channel. This channel can then be used to send the message to wherever you want.</p>
<p>As you could see, it was relatively easy to connect with a FTP server and retrieve the files. I hope this post helped you in setting up your own FTP connection with Spring Integration. All that rests us is waiting for official release of the Spring Integration Adapters.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jteam.nl/2010/07/21/connecting-to-ftp-server-with-spring-integration/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Parsing HTML with Jericho</title>
		<link>http://blog.jteam.nl/2010/07/14/parsing-html-with-jericho/</link>
		<comments>http://blog.jteam.nl/2010/07/14/parsing-html-with-jericho/#comments</comments>
		<pubDate>Wed, 14 Jul 2010 11:00:59 +0000</pubDate>
		<dc:creator>Roberto van der Linden</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[Jericho]]></category>
		<category><![CDATA[Parsing]]></category>

		<guid isPermaLink="false">http://blog.jteam.nl/?p=2368</guid>
		<description><![CDATA[In one of our projects I had to parse and manipulate HTML. After searching for a nice HTML parser, I ended up using the open source library Jericho HTML Parser. Jericho provides you a lot of features including text extraction from HTML markup, rendering, formatting or compacting HTML. In this post I will show you [...]]]></description>
			<content:encoded><![CDATA[<p>In one of our projects I had to parse and manipulate HTML. After searching for a nice HTML parser, I ended up using the open source library <a href="http://jericho.htmlparser.net/docs/index.html" target="_blank">Jericho HTML Parser</a>. Jericho provides you a lot of features including text extraction from HTML markup, rendering, formatting or compacting HTML. In this post I will show you a few of the features I have used.<br />
<span id="more-2368"></span></p>
<h2>Maven dependency</h2>
<p>If you use Maven, you can simply add the following dependency to use the library.</p>
<pre class="brush: xml;">
&lt;dependency&gt;
    &lt;groupid&gt;net.htmlparser.jericho&lt;/groupid&gt;
    &lt;artifactid&gt;jericho-html&lt;/artifactid&gt;
    &lt;version&gt;3.1&lt;/version&gt;
&lt;/dependency&gt;
</pre>
<h2>API</h2>
<p>I don’t want to explain all classes, but the following classes are basically the starting point of all your parsing.</p>
<ul>
<li><strong>Source</strong> – Represents a source HTML document. This is always the first step in parsing an HTML document.</li>
<li><strong>OutputDocument</strong> &#8211; Represents a modified version of an original Source document or Segment.</li>
<li><strong>Element</strong> &#8211; Represents an element  in a specific source document, which encompasses a start tag, an optional end tag and all content  in between.</li>
</ul>
<p>For a complete overview of all classes you can view the <a href="http://jericho.htmlparser.net/docs/javadoc/index.html" target="_blank">javadoc</a>.</p>
<h2>Extract all text</h2>
<p>To extract all the text from the HTML markup, all you have to do is the following:</p>
<pre class="brush: java;">
    public String extractAllText(String htmlText){
        Source source = new Source(htmlText);
        return source.getTextExtractor().toString();
    }
</pre>
<p>You define a new Source object that takes in our case a String as input. But it also accepts for example a InputStream or URL. The Source object contains a method getTextExtractor that allows you to, how surprising, extract the text. The TextExtractor class gives you a few options to configure the extraction. One of the options is that you can exclude text from a specified Element. You can also include an attribute. The value of that attribute will be included in the output.</p>
<h2>Manipulating HTML</h2>
<p>Manipulating HTML is very easy with Jericho. In the code example below I want to add an id attribute to all H2 elements to create anchor navigation. One again I create a Source document. From this Source document I create an OutputDocument.</p>
<p>The OutputDocument represents a modified version of the original Source document. With the list of all H2 elements retrieved from the Source, we now can ask for all the attributes of a single H2 element. If the attribute <em>id</em> already exists we do nothing, but if it does not we recreate the starttag with a new id attribute and all the other existing attributes from that H2 element.</p>
<p>As you can see in the example, it is relatively easy to manipulate attributes of an element. With the <a href="http://jericho.htmlparser.net/docs/javadoc/net/htmlparser/jericho/Attributes.html">Attributes</a> object you can get a List of Attribute objects that are found in the source document or in a starttag. These attributes are not modifiable. The outputDocument has a convenience method that allows us to replace the specific startTag with our newly created H2 start tag in order to add our <em>id</em> attribute.</p>
<pre class="brush: java;">
    public String addIdAttributeToH2Elements(String html) {
        Source source = new Source(html);
        OutputDocument outputDocument = new OutputDocument(source);
        List&lt;element&gt; h2Elements = source.getAllElements(&quot;h2&quot;);

        for (Element element : h2Elements) {
            StartTag startTag = element.getStartTag();
            Attributes attributes = startTag.getAttributes();
            Attribute idAttribute = attributes.get(&quot;id&quot;);

            if (idAttribute == null) {
                String elementValue = element.getTextExtractor().toString();
                String validAnchorId = AnchorUtils.getLowerCasedValidAnchorTitle(elementValue);

                StringBuilder builder = new StringBuilder();
                builder.append(&quot;&lt;h2&quot;).append(&quot; &quot;).append(&quot;id=\&quot;&quot;).append(validAnchorId).append(&quot;\&quot;&quot;);
                for (Attribute attribute : attributes) {
                    builder.append(&quot; &quot;);
                    builder.append(attribute);
                }
                builder.append(&quot;&gt;&quot;);

                outputDocument.replace(startTag, builder);
            }
        }

        return outputDocument.toString();
    }
</pre>
<h2>Remove Elements</h2>
<p>Just like me, you may want to remove a few tags from your HTML. Here is an example that shows you how you can achieve that.</p>
<pre class="brush: java;">
    private static final Set&lt;string&gt; ALLOWED_HTML_TAGS = new HashSet&lt;string&gt;(Arrays.asList(
            HTMLElementName.ABBR,
            HTMLElementName.ACRONYM,
            HTMLElementName.SPAN,
            HTMLElementName.SUB,
            HTMLElementName.SUP)
    );

    private static String removeNotAllowedTags(String htmlFragment) {
        Source source = new Source(htmlFragment);
        OutputDocument outputDocument = new OutputDocument(source);
        List&lt;element&gt; elements = source.getAllElements();

        for (Element element : elements) {
            if (!ALLOWED_HTML_TAGS.contains(element.getName())) {
                outputDocument.remove(element.getStartTag());
                if (!element.getStartTag().isSyntacticalEmptyElementTag()) {
                    outputDocument.remove(element.getEndTag());
                }
            }
        }

        return outputDocument.toString();
    }
</pre>
<p>In the example above you see that after checking if the tag is allowed, we need to remove the start and endtag. If you would remove the complete element, then you would also remove the text within these tags. The API allows you to check for elements that are empty. This can be handy to remove redundant empty elements or in my case to check if the starttag a self closing tag.</p>
<h2>Conclusion</h2>
<p>In this post I showed you how I have used Jericho, but Jericho has a lot more interesting features. On their webpage they provide more examples on how to use those features. Jericho provides a nice and clean API and makes the parsing of HTML really easy!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jteam.nl/2010/07/14/parsing-html-with-jericho/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Mahout – Taste :: Part Three – Estimators</title>
		<link>http://blog.jteam.nl/2010/07/08/mahout-%e2%80%93-taste-part-three-%e2%80%93-estimators/</link>
		<comments>http://blog.jteam.nl/2010/07/08/mahout-%e2%80%93-taste-part-three-%e2%80%93-estimators/#comments</comments>
		<pubDate>Thu, 08 Jul 2010 15:46:22 +0000</pubDate>
		<dc:creator>Frank Scholten</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Enterprise Search]]></category>
		<category><![CDATA[Collaborative Filtering]]></category>
		<category><![CDATA[Mahout]]></category>
		<category><![CDATA[Recommendations]]></category>
		<category><![CDATA[Taste]]></category>

		<guid isPermaLink="false">http://blog.jteam.nl/?p=2317</guid>
		<description><![CDATA[In Taste, estimators are the bridge between the generic item- or user recommendation logic and the specific similarity algorithm. Estimators are mainly used as part of the recommendation process, however, they are also used for evaluating recommenders. Additionally, the &#8216;recommended because&#8217; feature is also powered by an estimator. This blog covers some Taste internals and [...]]]></description>
			<content:encoded><![CDATA[<p>In Taste, estimators are the bridge between the generic item- or user recommendation logic and the specific similarity algorithm. Estimators are mainly used as part of the recommendation process, however, they are also used for evaluating recommenders. Additionally, the &#8216;recommended because&#8217; feature is also powered by an estimator. This blog covers some Taste internals and shows you how estimators are used within Taste via a few code samples.</p>
<p><span id="more-2317"></span></p>
<h3><strong>Estimators for recommendations</strong></h3>
<p>Let&#8217;s start with the main usage of estimators: providing recommendations. Suppose we create a <span style="font-family: 'courier new'; font-size: medium;">GenericItemBasedRecommender</span>, provide it with a <span style="font-family: 'courier new'; font-size: medium;">DataModel</span> and one of Taste&#8217;s <span style="font-family: 'courier new'; font-size: medium;">ItemSimilarity</span> implementations.</p>
<p>To fetch a few recommendations we call <span style="font-family: 'courier new'; font-size: medium;">GenericItemBasedRecommender.mostSimilarItems(long itemID, int howMany)</span>, as shown in the snippet below:</p>
<pre class="brush: java;">
  @Override
  public List&lt;RecommendedItem&gt; mostSimilarItems(long itemID, int howMany) throws TasteException {
    return mostSimilarItems(itemID, howMany, null);
  }

  @Override
  public List&lt;RecommendedItem&gt; mostSimilarItems(long itemID, int howMany,
                                                Rescorer&lt;LongPair&gt; rescorer) throws TasteException {
    TopItems.Estimator&lt;Long&gt; estimator = new MostSimilarEstimator(itemID, similarity, rescorer);
    return doMostSimilarItems(new long[] {itemID}, howMany, estimator);
  }
</pre>
<p>After delegating the method call to a more generic <span style="font-family: 'courier new'; font-size: medium;">mostSimilarItems</span> method, a <span style="font-family: 'courier new'; font-size: medium;">MostSimilarEstimator</span> is constructed and passed to the protected method <span style="font-family: 'courier new'; font-size: medium;">doMostSimilarItems</span>. The whole process of estimating and recommending is implemented via an estimator and algorithm specific logic within a recommender.</p>
<p>Now let&#8217;s zoom in on the <span style="font-family: 'courier new'; font-size: medium;">doMostSimilarItems</span> method. See the snippet below:</p>
<pre class="brush: java;">
  private List&lt;RecommendedItem&gt; doMostSimilarItems(long[] itemIDs,
                                                   int howMany,
                                                   TopItems.Estimator&lt;Long&gt; estimator) throws TasteException {
    DataModel model = getDataModel();
    FastIDSet possibleItemsIDs = new FastIDSet();
    for (long itemID : itemIDs) {
      PreferenceArray prefs = model.getPreferencesForItem(itemID);
      int size = prefs.length();
      for (int i = 0; i &lt; size; i++) {
        long userID = prefs.get(i).getUserID();
        possibleItemsIDs.addAll(model.getItemIDsFromUser(userID));
      }
    }
    possibleItemsIDs.removeAll(itemIDs);
    return TopItems.getTopItems(howMany, possibleItemsIDs.iterator(), null, estimator);
  }
</pre>
<p>The snippet above describes the core logic for item-based recommendation. This process consists of three steps:</p>
<ol>
<li>Fetch all preferences for the given item(s)</li>
<li>For each preference get the corresponding user and fetch all their other preferences</li>
<li>From this set of preferences, minus the given item, get the corresponding items and determine the top items based on the given estimator</li>
</ol>
<p>The <span style="font-family: 'courier new'; font-size: medium;">TopItems</span> is a helper class for fetching the top ranked items of a set of items for a given estimator.</p>
<p>Now on to the estimator. All estimators implement <span style="font-family: 'courier new'; font-size: medium;">TopItems.Estimator&lt;T&gt;</span> interface which is really simple. It returns an estimate for a &#8216;thing&#8217; as a double.</p>
<pre class="brush: java;">
  public interface Estimator&lt;T&gt; {
    double estimate(T thing) throws TasteException;
  }
</pre>
<p>Now on to the <span style="font-family: 'courier new'; font-size: medium;">MostSimilarEstimator<span>:</span></span></p>
<pre class="brush: java;">
  public static class MostSimilarEstimator implements TopItems.Estimator&lt;Long&gt; {

    private final long toItemID;
    private final ItemSimilarity similarity;
    private final Rescorer&lt;LongPair&gt; rescorer;

    public MostSimilarEstimator(long toItemID, ItemSimilarity similarity, Rescorer&lt;LongPair&gt; rescorer) {
      this.toItemID = toItemID;
      this.similarity = similarity;
      this.rescorer = rescorer;
    }

    @Override
    public double estimate(Long itemID) throws TasteException {
      LongPair pair = new LongPair(toItemID, itemID);
      if ((rescorer != null) &amp;&amp; rescorer.isFiltered(pair)) {
        return Double.NaN;
      }
      double originalEstimate = similarity.itemSimilarity(toItemID, itemID);
      return rescorer == null ? originalEstimate : rescorer.rescore(pair, originalEstimate);
    }
  }
</pre>
<p>This estimator does three things:</p>
<ol>
<li>Use the <span style="font-family: 'courier new'; font-size: medium;">Rescorer</span> to filter items. <span style="font-family: 'courier new'; font-size: medium;">Rescorers</span> can be used to create domain specific filtering of items</li>
<li>Use the <span style="font-family: 'courier new'; font-size: medium;">ItemSimilarity</span> to calculate the preference of a user for the given item</li>
<li>Optionally boost the similarity value with the <span style="font-family: 'courier new'; font-size: medium;">Rescorer</span></li>
</ol>
<p>This setup allows you to plugin arbitrary <span style="font-family: 'courier new'; font-size: medium;">ItemSimilarity</span> algorithms in the recommender.</p>
<h3><strong>Recommended because&#8230;</strong></h3>
<p>Another interesting feature of the <span style="font-family: 'courier new'; font-size: medium;">GenericItemBasedRecommender</span> is the &#8216;Recommended because&#8217; feature. With this feature you can determine <em>why</em> a certain item was recommended to you, i.e. <em>which of your preferences were largely responsible for giving you this recommendation</em>.</p>
<p>To use this feature call <span style="font-family: 'courier new'; font-size: medium;">recommendedBecause(long userID, long itemID, int howMany)</span>, see snippet below:</p>
<pre class="brush: java;">
  @Override
  public List&lt;RecommendedItem&gt; recommendedBecause(long userID, long itemID, int howMany) throws TasteException {
    if (howMany &lt; 1) {
      throw new IllegalArgumentException(&quot;howMany must be at least 1&quot;);
    }

    DataModel model = getDataModel();
    TopItems.Estimator&lt;Long&gt; estimator = new RecommendedBecauseEstimator(userID, itemID, similarity);

    PreferenceArray prefs = model.getPreferencesFromUser(userID);
    int size = prefs.length();
    FastIDSet allUserItems = new FastIDSet(size);
    for (int i = 0; i &lt; size; i++) {
      allUserItems.add(prefs.getItemID(i));
    }
    allUserItems.remove(itemID);

    return TopItems.getTopItems(howMany, allUserItems.iterator(), null, estimator);
  }
</pre>
<p>It takes all items the given user has a preferences for, minus the given item and passes this to <span style="font-family: 'courier new'; font-size: medium;">TopItems</span>, along the with <span style="font-family: 'courier new'; font-size: medium;">RecommendedBecauseEstimator</span>, see the code below:</p>
<pre class="brush: java;">
  private class RecommendedBecauseEstimator implements TopItems.Estimator&lt;Long&gt; {

    private final long userID;
    private final long recommendedItemID;
    private final ItemSimilarity similarity;

    private RecommendedBecauseEstimator(long userID, long recommendedItemID, ItemSimilarity similarity) {
      this.userID = userID;
      this.recommendedItemID = recommendedItemID;
      this.similarity = similarity;
    }

    @Override
    public double estimate(Long itemID) throws TasteException {
      Float pref = getDataModel().getPreferenceValue(userID, itemID);
      if (pref == null) {
        return Float.NaN;
      }
      double similarityValue = similarity.itemSimilarity(recommendedItemID, itemID);
      return (1.0 + similarityValue) * pref;
    }
  }

}
</pre>
<p>This <span style="font-family: 'courier new'; font-size: medium;">RecommendedBecauseEstimator</span> determines the ranking by multiplying the preference value of the user by the item similarity value of the current item pair. After this process the top ranked items are those items that were most important in causing a recommendation of the given item.</p>
<h3><strong>Conclusions</strong></h3>
<p>This concludes the overview of some Taste internals and has hopefully given you a clearer picture on how recommendations and estimators work inside Taste. In future posts I will probably expand on this topic, especially within the context the evaluation of recommenders. If you have any questions regarding Taste in general or this topic of estimators feel free to leave a comment.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jteam.nl/2010/07/08/mahout-%e2%80%93-taste-part-three-%e2%80%93-estimators/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Mahout &#8211; Taste at Lucene Eurocon and Berlin Buzzwords</title>
		<link>http://blog.jteam.nl/2010/07/01/mahout-taste-at-lucene-eurocon-and-berlin-buzzwords/</link>
		<comments>http://blog.jteam.nl/2010/07/01/mahout-taste-at-lucene-eurocon-and-berlin-buzzwords/#comments</comments>
		<pubDate>Thu, 01 Jul 2010 08:40:51 +0000</pubDate>
		<dc:creator>Frank Scholten</dc:creator>
				<category><![CDATA[Enterprise Search]]></category>
		<category><![CDATA[Collaborative Filtering]]></category>
		<category><![CDATA[Conference]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Mahout]]></category>
		<category><![CDATA[Recommendations]]></category>
		<category><![CDATA[Taste]]></category>

		<guid isPermaLink="false">http://blog.jteam.nl/?p=2308</guid>
		<description><![CDATA[A little while ago, I was delighted to present two introductory Mahout &#8211; Taste talks, at Lucene Eurocon and Berlin Buzzwords. I received quite a lot of good feedback about the presentations and have been asked by a few attendees to post them. If you&#8217;re one of those attendees or you missed the presentation, you [...]]]></description>
			<content:encoded><![CDATA[<p>A little while ago, I was delighted to present two introductory Mahout &#8211; Taste talks, at <a href="http://lucene-eurocon.org/">Lucene Eurocon</a> and <a href="http://www.berlinbuzzwords.de/">Berlin Buzzwords</a>. I received quite a lot of good feedback about the presentations and have been asked by a few attendees to post them.</p>
<p>If you&#8217;re one of those attendees or you missed the presentation, you can download the slides here:</p>
<ul>
<li><a href="http://lucene-eurocon.org/slides/Introduction-To-Collaborative-Filtering-Using-Mahout_Frank-Scholten.pdf">Lucene Eurocon Slides</a></li>
<li><a href="http://blog.jteam.nl/wp-content/uploads/2010/07/scholten_bbuzz2010.pdf">Berlin Buzzwords Slides</a></li>
</ul>
<p>At Lucene Eurocon, the first European conference on Lucene and Solr there were interesting presentations, ranging from practical relevance to language analysis. For me it was fun to give a practical presentation about recommendations as a complementary feature to search applications. I hope you find the presentation useful if you&#8217;re trying to work out how to build a recommender &#8211; I used the movielens dataset as an example in the presentation and based the code on my earlier <a href="http://blog.jteam.nl/2010/04/15/mahout-taste-part-two-getting-started/">&#8216;getting started&#8217;</a> blog.</p>
<p>I also really enjoyed doing the Berlin Buzzwords presentation and meeting up with people from the Mahout community and other attendees. This conference focused mainly on NoSQL, scalability and Hadoop. However, from my talks with people there I sense that there&#8217;s growing interest in Mahout. You should find the presentation useful if you want to know more about different algorithms and how to evaluate them. I will blog about this topic in more detail soon.</p>
<p>Until then, I&#8217;d love to hear some feedback on what you think of the presentations!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jteam.nl/2010/07/01/mahout-taste-at-lucene-eurocon-and-berlin-buzzwords/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Top Free Android Applications</title>
		<link>http://blog.jteam.nl/2010/05/19/top-free-android-applications/</link>
		<comments>http://blog.jteam.nl/2010/05/19/top-free-android-applications/#comments</comments>
		<pubDate>Wed, 19 May 2010 12:58:52 +0000</pubDate>
		<dc:creator>Roberto van der Linden</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[Apps]]></category>
		<category><![CDATA[Mobile]]></category>

		<guid isPermaLink="false">http://blog.jteam.nl/?p=2266</guid>
		<description><![CDATA[Since a week I have the latest Android phone of Sony Ericsson, the X10. As it is my first Android phone, the first thing I did was searching the Android Market for great apps to get the maximum out of my Android system. In this post I will show you my selection of apps that [...]]]></description>
			<content:encoded><![CDATA[<p>Since a week I have the latest Android phone of Sony Ericsson, the X10. As it is my first Android phone, the first thing I did was searching the Android Market for great apps to get the maximum out of my Android system.</p>
<p>In this post I will show you my selection of apps that I found useful, interesting or just fun to have.</p>
<p><span id="more-2266"></span></p>
<h2>The useful apps</h2>
<h3>9292ov Pro</h3>
<p><a href="http://blog.jteam.nl/wp-content/uploads/2010/05/9292ov.png"><img style="margin: 0px 10px 0px 0px; display: inline; border: 0px;" title="9292ov" src="http://blog.jteam.nl/wp-content/uploads/2010/05/9292ov_thumb.png" border="0" alt="9292ov" width="48" height="48" align="left" /></a>This application allows you to plan your trip with all Dutch public transport. It also shows you how much you must pay for the tickets and you can share your advise via mail or Twitter. Furthermore, it holds a list of all delays, allows you to save your advise or explore places of departure or arrival locations by using the map function. And for the people that can not read Dutch, it’s also available in English.</p>
<h3>ES File Explorer</h3>
<p><a href="http://blog.jteam.nl/wp-content/uploads/2010/05/esfileexplorer.png"><img style="margin: 0px 10px 0px 0px; display: inline; border: 0px;" title="es file explorer" src="http://blog.jteam.nl/wp-content/uploads/2010/05/esfileexplorer_thumb.png" border="0" alt="es file explorer" width="48" height="48" align="left" /></a>There are a lot of file managers in the Market, but I chose this one, because it has a good interface that doesn’t hurt my eyes and has a few interesting features. It has support for FTP and allows you to manage/(un)install your apps. Beside managing your files on the phone, you can also manage your files on a PC via LAN.</p>
<h3>Task Manager</h3>
<p><a href="http://blog.jteam.nl/wp-content/uploads/2010/05/taskmanager.png"><img style="margin: 0px 10px 0px 0px; display: inline; border: 0px;" title="task manager" src="http://blog.jteam.nl/wp-content/uploads/2010/05/taskmanager_thumb.png" border="0" alt="task manager" width="48" height="48" align="left" /></a> Android keep your application open at the background. This is really nice, but also can make you phone slow or maybe even worse, drain your battery. Task Manager allows you to close these applications. Just like the file manager, there are a lot of these apps. I think that this one, is a nice and simple application, that is easy to understand and easy to use.</p>
<h3>JuiceDefender</h3>
<p><a href="http://blog.jteam.nl/wp-content/uploads/2010/05/juicedefender.png"><img style="margin: 0px 10px 0px 0px; display: inline; border: 0px;" title="juice defender" src="http://blog.jteam.nl/wp-content/uploads/2010/05/juicedefender_thumb.png" border="0" alt="juice defender" width="48" height="48" align="left" /></a>The batteries of smart phones in general don’t last really long. Juice Defender is an app that saves power and extends your battery life by controlling the data connection and WiFi of the device. You can schedule the activation of the data connection or even turn it off. I have scheduled it to enable my data connection for 1 minute every 15 minutes. You also have an ultimate (paid) version, which give you more possibilities.</p>
<h3>ConnectBot</h3>
<p><a href="http://blog.jteam.nl/wp-content/uploads/2010/05/connectbot.png"><img style="margin: 0px 10px 0px 0px; display: inline; border: 0px;" title="connectbot" src="http://blog.jteam.nl/wp-content/uploads/2010/05/connectbot_thumb.png" border="0" alt="connectbot" width="48" height="48" align="left" /></a>Every developer wants to have a SSH client on this mobile phone <img src='http://blog.jteam.nl/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> . ConnectBot is one of the available clients in the Market. It can manage simultaneous SSH sessions, copy/paste between other applications and even create secure tunnels.</p>
<h2>The show off apps</h2>
<h3>Google Goggles</h3>
<p><a href="http://blog.jteam.nl/wp-content/uploads/2010/05/goggles.png"><img style="margin: 0px 10px 0px 0px; display: inline; border: 0px;" title="goggles" src="http://blog.jteam.nl/wp-content/uploads/2010/05/goggles_thumb.png" border="0" alt="goggles" width="48" height="48" align="left" /></a>With Google Goggles you can search for an object with your camera phone. It can identify text, landmarks, books, contact info, artwork, places. wine and logos. With your camera you make a picture, which will be analyzed. If the object is recognized, the app will provide you with the found information.  It works quite good and is really a must have app on your android phone.</p>
<h3>Google Sky Maps</h3>
<p><a href="http://blog.jteam.nl/wp-content/uploads/2010/05/skymaps.png"><img style="margin: 0px 10px 0px 0px; display: inline; border: 0px;" title="sky maps" src="http://blog.jteam.nl/wp-content/uploads/2010/05/skymaps_thumb.png" border="0" alt="sky maps" width="48" height="48" align="left" /></a>Google Sky Maps lets you discover and browse the night sky. It uses your phone’s orientation sensors to show you a star map for your location. You can search for planets, stars, constellations and the application will point you to the right direction. Since version 1.5 they added image of <a href="http://www.hubblesite.org/" target="_blank">Hubble</a>.</p>
<h3>Layer Reality Browser</h3>
<p><a href="http://blog.jteam.nl/wp-content/uploads/2010/05/layar.png"><img style="margin: 0px 10px 0px 0px; display: inline; border: 0px;" title="layar" src="http://blog.jteam.nl/wp-content/uploads/2010/05/layar_thumb.png" border="0" alt="layar" width="48" height="48" align="left" /></a>Layar is an augmented reality browser that, as they say it, shows you the things you can’t see. The app is provided with hundreds of layers (free and paid) that allows you to find the most useful things as hotels and restaurants or the most crazy things as your Avatar’s body. The Layar Catalog contains a lot of local and international layers. You (or JTeam) can even create your own layer. Really cool and also useful for finding things nearby.</p>
<h2>The fun apps</h2>
<h3>Ringdroid</h3>
<p><a href="http://blog.jteam.nl/wp-content/uploads/2010/05/ringdroid.png"><img style="margin: 0px 10px 0px 0px; display: inline; border: 0px;" title="ringdroid" src="http://blog.jteam.nl/wp-content/uploads/2010/05/ringdroid_thumb.png" border="0" alt="ringdroid" width="48" height="48" align="left" /></a>Ringdroid is a ringtone creator. This app lets you manipulate any song of your phone. After you have selected a song you can easily select a part of the song via two sliders. If you have selected the right part, you can save the song. Ringdroid then gives you the option to use the song as a ringtone and/or a notification.</p>
<h3>Abduction</h3>
<p><a href="http://blog.jteam.nl/wp-content/uploads/2010/05/abduction.png"><img style="margin: 0px 10px 0px 0px; display: inline; border: 0px;" title="abduction" src="http://blog.jteam.nl/wp-content/uploads/2010/05/abduction_thumb.png" border="0" alt="abduction" width="48" height="48" align="left" /></a>Abduction is an addictive game for your Android phone. Your herd has been abducted by aliens, so now you have to save your friends. It uses the accelerometer, meaning you have to tilt your phone to make your way up to the aliens. To get to the spaceship you have to bounce up in a series of platforms. It has nice graphics and it is a good time-wasting game.</p>
<h3>Epic Fails</h3>
<p><a href="http://blog.jteam.nl/wp-content/uploads/2010/05/epicfails.png"><img style="margin: 0px 10px 0px 0px; display: inline; border: 0px;" title="epic fails" src="http://blog.jteam.nl/wp-content/uploads/2010/05/epicfails_thumb.png" border="0" alt="epic fails" width="48" height="48" align="left" /></a>The term “epic fail” is popular on the Internet. People place it onto photos or short videos that depict unsuccessful events or people falling short of expectations. Epic Fails shows you the most hilarious fail pictures. Nothing more, but extremely funny to show to your friends. You can share the pictures with your friends via all kind of applications like mail, facebook or picasa.</p>
<h3>PicSay</h3>
<p><a href="http://blog.jteam.nl/wp-content/uploads/2010/05/picsay.png"><img style="margin: 0px 10px 0px 0px; display: inline; border: 0px;" title="picsay" src="http://blog.jteam.nl/wp-content/uploads/2010/05/picsay_thumb.png" border="0" alt="picsay" width="48" height="48" align="left" /></a>PicSay is a photo editor. You can add effects, word-balloons, titles and graphics. The pro (paid) version contains a lot more features and is propably more worthwhile. It has an intuitive interface, which is easy to use. I had a little bit of trouble to resize the items, but you probably just have to get used to it.</p>
<h2>JTeam and Android</h2>
<p>Within JTeam we have the knowledge and experience to create Android applications. So if you have a great idea for an application or maybe want to have a mobile app version of your website, you can contact us by filling in the contact form <a href="http://www.jteam.nl/contact" target="_blank">here</a> and we can help you conquer the Android world.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jteam.nl/2010/05/19/top-free-android-applications/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>JTeam Partners with New Relic to Provide Application Performance Management for Solr Enterprise Search Server</title>
		<link>http://blog.jteam.nl/2010/05/11/jteam-partners-with-new-relic-to-provide-application-performance-management-for-solr-enterprise-search-server/</link>
		<comments>http://blog.jteam.nl/2010/05/11/jteam-partners-with-new-relic-to-provide-application-performance-management-for-solr-enterprise-search-server/#comments</comments>
		<pubDate>Tue, 11 May 2010 15:18:59 +0000</pubDate>
		<dc:creator>Jenny Nguyen</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[APM]]></category>
		<category><![CDATA[Lucene]]></category>
		<category><![CDATA[New Relic]]></category>
		<category><![CDATA[New Relic RPM]]></category>
		<category><![CDATA[Solr]]></category>

		<guid isPermaLink="false">http://blog.jteam.nl/2010/05/11/jteam-partners-with-new-relic-to-provide-application-performance-management-for-solr-enterprise-search-server/</guid>
		<description><![CDATA[JTeam will now offer leading on-demand APM tool to monitor, troubleshoot and optimize deployments of Solr search server JTeam today announced that it has partnered with New Relic, Inc., to make New Relic RPM available to its clients during consulting engagements. JTeam consultants and clients can now use RPM collaboratively to monitor, troubleshoot, and optimize [...]]]></description>
			<content:encoded><![CDATA[<p>JTeam will now offer leading on-demand APM tool to monitor, troubleshoot and optimize deployments of Solr search server</p>
<p>JTeam today announced that it has partnered with New Relic, Inc., to make New Relic RPM available to its clients during consulting engagements. JTeam consultants and clients can now use RPM collaboratively to monitor, troubleshoot, and optimize live production web applications and Solr instances, and thus ensure successful application deployments and a superior Web user experience.</p>
<p>New Relic, Inc. is the leading software-as-a-service provider of application performance management (APM) solutions. Its flagship product, New Relic RPM, is an on-demand performance management solution for web applications developed in Java, Ruby, or JRuby and provides deep, 24&#215;7 visibility and code-level diagnostics for web applications deployed on traditional, dedicated infrastructures or in the cloud. New Relic recently announced RPM’s ability to provide deep visibility into production Solr instances.  To learn more about New Relic RPM and Solr monitoring go to <a href="http://www.newrelic.com/solr.html" target="_blank">http://www.newrelic.com/solr.html</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jteam.nl/2010/05/11/jteam-partners-with-new-relic-to-provide-application-performance-management-for-solr-enterprise-search-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
