<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8661585878226033328</id><updated>2026-05-01T00:04:37.632-07:00</updated><category term="&quot;windows phone 7&quot;"/><category term="Linq2sql notSupportedException ArrayLength Linq &quot;Entity Framework&quot;"/><category term="WF3"/><category term="WF4"/><category term="Workflow"/><category term="andorid"/><category term="android"/><category term="ave.exe virus"/><category term="bre"/><category term="conversion"/><category term="git"/><category term="gogtasks"/><category term="google"/><category term="gtasks"/><category term="hg"/><category term="mercurial"/><category term="rules"/><category term="tasks"/><category term="visual-studio-online"/><category term="wp7"/><title type='text'>Frode Nilsen&#39;s Techblog</title><subtitle type='html'>Diverse IT technology-related posts and rants</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>29</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-9111322685366349249</id><published>2022-12-20T04:41:00.006-08:00</published><updated>2022-12-20T07:42:55.747-08:00</updated><title type='text'>Declarative UI and UDF with Android Databinding in XML</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;
I know: A lot of buzzwords. Except Databinding, which is kind of the opposite. The thing is I&#39;ve been a big fan of Android Databinding since its release in 2016 because I think it did good for a lot of the architectural issues that Android was suffering from. When Jetpack Compose came along people praised it for many good reasons but also for wrong ones. The word &quot;declarative&quot; was thrown around a lot, and conversely &quot;imperative&quot; when talking about legacy Android XML (example sources: (&lt;a href=&quot;https://www.section.io/engineering-education/declarative-vs-imperative-ui-android/&quot;&gt;[1]&lt;/a&gt;, &lt;a href=&quot;https://fakhrulasa.me/android-ui&quot;&gt;[2]&lt;/a&gt;, &lt;a href=&quot;https://blog.kotlin-academy.com/say-hello-to-jetpack-compose-and-compare-with-xml-6bc6053aec13&quot;&gt;[3]&lt;/a&gt;). I felt that we were given the option to do declarative UI architecture already with Android Databinding but everyone seemed to have missed. Was I crazy? 

&lt;p&gt;
  With the example project shown below I wanted to prove to myself that declarative UI could be done with Android XML Databinding. As a developer with &quot;senior&quot; in the title, I&#39;m obliged to truly understand the meaning behind the buzzwords in the title of this post. If you too are an Android developer feeling the slightest uncertainty about the meaning of those, please grant yourself a couple of minutes to read and understand as well. And if I&#39;ve missed anything or misunderstood I&#39;m happy to be corrected.

&lt;p&gt;
What I made is a &lt;a href=&quot;https://github.com/Nilzor/declarative-databinding&quot;&gt;a proof of concept app&lt;/a&gt; that illustrates how Android Databinding with XML can be declarative - simply by using a declarative ViewModel written for compose and applying that to a databound XML view. I will go in depth about that in a second - but first a bit more about the terms &quot;declarative&quot; and &quot;imperative&quot;:
&lt;/p&gt;

&lt;h2&gt;Making XML with Databinding declarative&lt;/h2&gt;
&lt;p&gt;
First of all, there&#39;s nothing inherent in XML combined with Java/Kotlin that makes it imperative. The language expressing the UI does not define the UI paradigm. It&#39;s how you use that language. I think StackOverflow is a good source for finding the consensus here. I&#39;m not saying &quot;truth&quot; because I&#39;m not sure there is a single truth. &lt;a href=&quot;https://medium.com/@adamzerner/declarative-vs-imperative-bca997d54bb4&quot;&gt;Some say it is a spectrum&lt;/a&gt; and not a binary definiton. 
&lt;/p&gt;
&lt;p&gt;
Anyway, &lt;a href=&quot;https://softwareengineering.stackexchange.com/a/173358/37254&quot;&gt;this accepted answer&lt;/a&gt; states:
&lt;/p&gt;
&lt;blockquote&gt;
The term is more often used for UI frameworks with a strict separation of the look of the UI from the behavior, which means the code reacting to UI events. For example, using XAML, you declare the look of your UI in a specific XML dialect, but you implement the behavior in separate program code.
&lt;/blockquote&gt;
&lt;p&gt;
Notice how he uses XAML as an example here. XAML is XML, just as Android&#39;s legacy view system is. It&#39;s not the markup lanugage, is the fact that we often use events to procedurally mutate dependent views that make it declarative. Oh and separation of looks from behaviour? Definitely well separated. They&#39;re even in different langauges as opposed to Compose.
&lt;/p&gt;
&lt;p&gt;
&lt;a href=&quot;https://softwareengineering.stackexchange.com/a/173359/37254&quot;&gt;The other answer&lt;/a&gt; is good as well, as it highlights that it&#39;s about describing WHAT instead of HOW. A view that&#39;s repeated in &lt;a href=&quot;https://www.section.io/engineering-education/declarative-vs-imperative-ui-android/&quot;&gt;this blog post&lt;/a&gt; from Luns Muema.
&lt;/p&gt;
&lt;blockquote&gt;
Declarative UI is a UI that&#39;s designed in a declarative way (you describe what it should be like) rather than an imperative way (you code the steps to create it.)
&lt;/blockquote&gt;
&lt;p&gt;
The definition used by &lt;a href=&quot;https://docs.flutter.dev/get-started/flutter-for/declarative&quot;&gt;the Flutter documentation&lt;/a&gt; (which is a declarative UI framework) also resonnates surprisingly well with Databinding in XML if you use it the way I do here.
&lt;/p&gt;

&lt;blockquote&gt;
Here, rather than mutating an old instance b when the UI changes, Flutter constructs new Widget instances. The framework manages many of the responsibilities of a traditional UI object (such as maintaining the state of the layout) behind the scenes with RenderObjects. RenderObjects persist between frames and Flutter’s lightweight Widgets tell the framework to mutate the RenderObjects between states. The Flutter framework handles the rest.
&lt;/blockquote&gt;

As in Compose and in this example, Flutter uses immutable state. &lt;i&gt;The framework&lt;/i&gt;, Flutter, constructs new widget instances. In our case, &lt;i&gt;the Databinding framework&lt;/i&gt;, constructs new widget instances or mutates existing.
&lt;p&gt;
I&#39;ll take one more example: &lt;a href=&quot;https://kaaneneskpc.medium.com/procedural-imperative-ui-vs-declerative-ui-and-approach-on-the-android-side-1725275c53f4&quot;&gt;This blog post&lt;/a&gt; by Kaan Enes states

&lt;blockquote&gt;
A declarative UI pattern defines the UI as a function of the “state.” A “state” is nothing but a variable or an object that holds a value, which can change based on user input or other business logic. When the state changes, the framework will redraw the UI
&lt;/blockquote&gt;

Again, this is exactly what happens with my immutable state bound to data in XML below.

&lt;h2&gt;What I did&lt;/h2&gt;
So let&#39;s get one thing straight first. Android Databinding out of the box is not inherently declarative. I had to come up with a set of rules you need to follow to get both a 100% declarative pattern and unidirectional data flow (UDF) working:
&lt;p&gt;
  &lt;ol&gt;
    &lt;li&gt;One-way databinding only. The second we introduce two-way binding we mutate view state.
    &lt;li&gt;Never write logic in your XML binding. Instead bind to a single property from the ViewModel.
    &lt;li&gt;Your view state must be immutable
    &lt;li&gt;Your view model must expose one single observable field: The view state
&lt;/ol&gt;
&lt;/p&gt;
&lt;p&gt;
  For point 1 this means that you have to stick to &lt;code&gt;@{viewModel.prop}&lt;/code&gt; only, never the &lt;code&gt;@={}&lt;/code&gt;-syntax. So for instance for EditText&#39;s where it would be natural to use two-way binding for the text property in traditional Android Databinding, you&#39;d instead have to bind to the event &lt;code&gt;onTextChanged&lt;/code&gt; and let the ViewModel create a new state from that.
&lt;/p&gt;
&lt;p&gt;
To elaborate on number 2: Not under any circumstance should you write expressions in XML:
  &lt;ul&gt;&lt;li&gt;&lt;code&gt;android:text=&quot;@{state.name}&quot;&lt;/code&gt; is cool. 
    &lt;li&gt;&lt;code&gt;android:visibility=&quot;@{state.personList != null &amp;amp;&amp;amp; state.personList.count &gt; 0}&quot;&lt;/code&gt; is horrible and you should take a four month unpaid leave to contemplate about your life choices.
&lt;/ul&gt;
This is a good rule even if you don&#39;t go for declarative UI. It simply makes the code more testable.
&lt;p&gt;
Point 3 and 4 from above should be familiar if you&#39;ve done Compose.
&lt;p&gt;
This diagram illustrates the setup:
&lt;p&gt;

&lt;img src=&quot;http://data.nilzorblog.com/blogposts/declarative/xml-binding.png&quot; width=450/&gt;
&lt;p&gt;
  If you&#39;ve written compose apps you should be familiar with differentiating between ViewModel and ViewState:
  &lt;ul&gt;
    &lt;li&gt;The ViewModel is the Kotlin file that inherits from androidx.lifecycle.ViewModel and has the responsibility of changing the state. &quot;Changing&quot; means copying the state and changing one or more properties. You may bind events to the ViewModel but not properties. 
    &lt;li&gt;The ViewState is an immutable Kotlin class that represents whatever changable state you see in the view. This is where you bind your XML properties to.
&lt;/ul&gt;
&lt;p&gt;
So this sets the stage for declarative UI where the state defines the UI completely and you can do cool stuff like state history playback.

&lt;h2&gt;Unidirectional Data Flow&lt;/h2&gt;
UDF is &lt;a href=&quot;https://developer.android.com/jetpack/compose/architecture&quot;&gt;an important concept in Compose&lt;/a&gt;. You need to understand that properly in order to succeed with declarative architecture with Databinding. The basics is that events bubble up and state trickle down in the view hierarchy. Let&#39;s take this trivial example:
&lt;p&gt;
You have a password input field and a &quot;Continue&quot; button. Whenever the password field is empty the Continue button should be disabled. Once a single character is entered, the buttons should enable. Illustrated:
  
 &lt;p&gt;
&lt;img src=&quot;http://data.nilzorblog.com/blogposts/declarative/pwd-disabled.png&quot;/&gt;
  &lt;p&gt;
&lt;img src=&quot;http://data.nilzorblog.com/blogposts/declarative/pwd-enabled.png&quot;/&gt;
&lt;p&gt;

  With UDF and declarative programming you do &lt;i&gt;not&lt;/i&gt; let the EditText alter the button state directly. Nor do you let the Button read the state of the EditText to determine its enabled-state (although that may comply to declarativism but not UDF?). Instead you let the textChanged-event bubble up to the ViewModel, which alter the state object and passes it down to the button. 
 &lt;p&gt; 
&lt;img src=&quot;http://data.nilzorblog.com/blogposts/declarative/udf-simple.png&quot; width=300/&gt;
&lt;/p&gt;
&lt;h2&gt;Example project&lt;/h2&gt;
&lt;p&gt;
Github link: &lt;a href=&quot;https://github.com/Nilzor/declarative-databinding&quot;&gt;https://github.com/Nilzor/declarative-databinding&lt;/a&gt;

&lt;p&gt;
The example project I wrote is a bit more complicated. It is the sketch of an app selling public transport tickets with an arbitrary number of traveler type categories. I&#39;ve set the data to have three categories: Adult, Child and Bicycle. You enter the number of each category by using increase/decrease buttons and get a total summed at the bottom
&lt;p&gt;
&lt;img src=&quot;http://data.nilzorblog.com/blogposts/declarative/example-proj.png&quot; width=380/&gt;
&lt;/p&gt;

The project is implemented both using Jetpack Compose and XML Databinding. It shares a common ViewModel and ViewState. There is just a thin wrapper around the ViewModel to allow the Android Databinding to pick up on changes. I convert the StateFlow to an Observable. You can see that in the file &lt;a href=&quot;https://github.com/Nilzor/declarative-databinding/blob/9b071faf10103314c8247da2497c99ac1ff5f058/app/src/main/java/no/nilsen/compose/databinding/ShoppingCartViewModelDatabinding.kt&quot;&gt;ShoppingCartViewModelDataBinding&lt;/a&gt;.
&lt;p&gt;
&lt;img src=&quot;http://data.nilzorblog.com/blogposts/declarative/same-viewmodel.png&quot; width=400&gt; 
&lt;p&gt;
If you look at the ViewState it represents the views pretty much one-to-one:
&lt;p&gt;
&lt;img src=&quot;http://data.nilzorblog.com/blogposts/declarative/state-hierarchy.png&quot; width=380/&gt;
&lt;/p&gt;
The challenge here lies in the introduction of the list (RecyclerView for the XML). You need to propagage the event happening at the leaf node when you increase or decrease the traveler count to the top and then alter the &quot;Total count&quot;. With Jetpack Compose this is pretty trivial. With Databinding you have to do a bit more grunt work. First of all I use Evan Tatarka&#39;s &lt;a href=&quot;https://github.com/evant/binding-collection-adapter&quot;&gt;binding-collection-adapter&lt;/a&gt; which allows me to databind to list items without writing adapters (more &lt;a href=&quot;https://www.nilzorblog.com/2022/08/filling-gaps-of-android-databinding.html&quot;&gt;tips here&lt;/a&gt;). But I then encountered the issue that the elements in the list do not have access to the root ViewModel for event propagation. It is bound directly to the sub-state that only expose a single list item. There might be several ways to solve this but I chose to bind the event directly to the root Activity, as that is always &quot;exposed&quot; by simply using the legacy &lt;code&gt;android:onClick=&quot;handleClick&quot;&lt;/code&gt; syntax, which requires of you to write a function in the Activity that takes a single View parameter as input. The activity then passes that event on to the ViewModel. There may be better ways to solve this, but it worked for me. The architecture for Databinding is then a slightly altered:
&lt;p&gt;
 
&lt;img src=&quot;http://data.nilzorblog.com/blogposts/declarative/udf-with-activity.png&quot; width=380/&gt;
&lt;p&gt;
  
&lt;h2&gt;Example flow&lt;/h2&gt;
I know you all don&#39;t have time to download the example project so here I illustrate a flow of three steps with the state data model alongside screenshots for both the Jetpack Compose rendering and Android XML Databinding:
&lt;p&gt;
  &lt;p&gt;
    &lt;ul&gt;
      &lt;li&gt;State 1: Add 1 adult
      &lt;li&gt;State 2: Add 1 child (sum: 1 adult, 1 child)
      &lt;li&gt;State 3: Add 1 child (sum: 1 adult, 2 children)
&lt;/ul&gt;   
&lt;/p&gt;
&lt;p&gt;
    &lt;pre style=&quot;display:inline-block&quot;&gt;
STATE 1    
    
PageState(
  productList = [
	  ProductCounterState(
		count = 1
		enableDecrease = true
		name = &quot;Adult&quot;
	  ),
	  ProductCounterState(
		count = 0
		enableDecrease = false
		name = &quot;Child&quot;
	  ),
	  ProductCounterState(
		count = 0
		enableDecrease = false
		name = &quot;Bicycle&quot;
	  )
	]
  totalProductCount = 1
)
    &lt;/pre&gt;
&lt;pre  style=&quot;display:inline-block&quot;&gt;
STATE 2

PageState(
  productList = [
	  ProductCounterState(
		count = 1
		enableDecrease = true
		name = &quot;Adult&quot;
	  ),
	  ProductCounterState(
		count = 1
		enableDecrease = true
		name = &quot;Child&quot;
	  ),
	  ProductCounterState(
		count = 0
		enableDecrease = false
		name = &quot;Bicycle&quot;
	  )
	]
  totalProductCount = 2
)
&lt;/pre&gt;
&lt;pre  style=&quot;display:inline-block&quot;&gt;
STATE 3

PageState(
  productList = [
	  ProductCounterState(
		count = 1
		enableDecrease = true
		name = &quot;Adult&quot;
	  ),
	  ProductCounterState(
		count = 2
		enableDecrease = true
		name = &quot;Child&quot;
	  ),
	  ProductCounterState(
		count = 0
		enableDecrease = false
		name = &quot;Bicycle&quot;
	  )
	]
  totalProductCount = 3
)

&lt;/pre&gt;

&lt;h3&gt;Compose screenshots&lt;/h3&gt;
&lt;img src=&quot;http://data.nilzorblog.com/blogposts/declarative/c1.png&quot; width=250&gt; 
&lt;img src=&quot;http://data.nilzorblog.com/blogposts/declarative/c2.png&quot; width=250&gt; 
&lt;img src=&quot;http://data.nilzorblog.com/blogposts/declarative/c3.png&quot; width=250&gt; 

&lt;h3&gt;Databinding screenshots&lt;/h3&gt;
&lt;img src=&quot;http://data.nilzorblog.com/blogposts/declarative/d1.png&quot; width=250&gt; 
&lt;img src=&quot;http://data.nilzorblog.com/blogposts/declarative/d2.png&quot; width=250&gt; 
&lt;img src=&quot;http://data.nilzorblog.com/blogposts/declarative/d3.png&quot; width=250&gt; 

&lt;p&gt;

In short: The presentation is correct both for Compose and Databining with a code base that share the exact same ViewModel/ViewState file. There is no noticable lag or flickering in the UI for any of the view implementations. 
&lt;p&gt;  
The example project also contains a bonus rewind / replay functionality for the databinding example for those who want to play around with that. Notice the buttons on the bottom of the activity when starting the Databinding Activity (cropped out of the screenshots). This was trivial to implement by wrapping the ViewModel in a &lt;a href=&quot;https://github.com/Nilzor/declarative-databinding/blob/main/app/src/main/java/no/nilsen/compose/common/HistoryViewModel.kt#L9&quot;&gt;history-holder&lt;/a&gt;.
    
&lt;h2&gt;Conclusion&lt;/h2&gt;
I did this experiment to prove to myself that I understood what declarative UI really was and that my gut feeling that you could do declarative UI in with Android Databinding in XML. I&#39;m not saying that I will use use this pattern going forward or that I recommend others to use it, but you should be aware of the possibility. If your app contains legacy Android XML views with imperative logic and you&#39;re looking to rewrite it, it will be just a big of a job to go to Delcarative XML using Databinding as it would be to rewrite it to Jetpack Compose. The latter option would be the best options in most cases, as Jetpack Compose has a bunch of other benefits that I have not dug into here. 
&lt;p&gt;
Jetpack Compose is awesome, but Android databinding with XML can be awesome too if used correctly.
</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/9111322685366349249'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/9111322685366349249'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2022/12/declarative-ui-and-udf-with-android.html' title='Declarative UI and UDF with Android Databinding in XML'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-5160745603183763618</id><published>2022-08-28T11:01:00.000-07:00</published><updated>2022-08-28T11:01:03.570-07:00</updated><title type='text'>Filling the gaps of Android Databinding</title><content type='html'>&lt;p&gt;
  &lt;img src=&quot;http://data.nilzorblog.com/blogposts/databinding-filling/illu4.png&quot; border=1 /&gt;
&lt;/p&gt;

&lt;h2&gt;tl;dr&lt;/h2&gt;
&lt;p&gt;
&lt;table class=&quot;grid-1&quot;&gt;
  &lt;tr&gt;&lt;th&gt;Library&lt;th&gt;Description&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://developer.android.com/topic/libraries/data-binding/binding-adapters&quot;&gt;binding-collection-adapter&lt;/a&gt;&lt;td&gt;Bind RecyclerView, ListView, ViewPager and Spinner&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/Nilzor/bindable-radiobuttons&quot;&gt;bindable-radiobuttons&lt;/a&gt;&lt;td&gt;Bind RadioButton, ToggleButton, Checkbox and lists of Buttons&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://gist.github.com/Nilzor/13ffe6216b4a444011bee48de5796bce&quot;&gt;useful BindingAdapter&lt;/a&gt;&lt;td&gt;Reduce boilerplate further and the need for common support properties&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;

The Android Databinding library is tried and tested tool for enabling MVVM architecture in your Android apps. It helps you move code from your activities, fragments and views to your ViewModel. From the outset the library lacked what I belive to be some core features, like binding to RecyclerView and groups of RadioButtons. In this article I will present a couple of libraries that fill these gaps and more.&amp;nbsp;
&lt;p&gt;
  With these simple add-ons I believe DataBinding is a highly effective and &lt;b&gt;fun&lt;/b&gt; way of coding solid unit-testable MVVM apps on Android.
&lt;/p&gt;

&lt;h2&gt;List- And RecyclerViews&lt;/h2&gt;
Evan Tatarka&#39;s &lt;a href=&quot;https://github.com/evant/binding-collection-adapter&quot;&gt;Binding-Collection-Adapter&lt;/a&gt; library solves binding to RecyclerViews elegantly. You have one XML view for the individual items and a ViewModel class that represents them. If you have multiple view types for the list you can override the binding code.
&lt;p&gt;
This solution rids of the adapter. Less code. Better architecture. It also suppoerts ListView, Spinner and ViewPager

&lt;h3&gt;Example&lt;/h3&gt;
Below is a minimal example to lay out the concept. A RecyclerView with two bound, each item has the text and the color property bindable. Read the official documentation for a complete, compilable example.
&lt;p&gt;
&lt;i&gt;Result:&lt;/i&gt;&lt;p&gt;
&lt;img src=&quot;http://data.nilzorblog.com/blogposts/databinding-filling/recyclerview.png&quot; width=60 border=1&gt;
&lt;p&gt;
&lt;i&gt;Main view:&lt;/i&gt;
&lt;pre&gt;&lt;code class=&quot;xml&quot;&gt;&amp;lt;androidx.recyclerview.widget.RecyclerView
	android:layout_width=&amp;quot;match_parent&amp;quot;
	android:layout_height=&amp;quot;match_parent&amp;quot;
	app:layoutManager=&amp;quot;androidx.recyclerview.widget.LinearLayoutManager&amp;quot;
	app:items=&amp;quot;@{viewModel.items}&amp;quot;
	app:itemBinding=&amp;quot;@{viewModel.itemBinding}&amp;quot;/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
&lt;i&gt;Item view:&lt;/i&gt;
&lt;pre&gt;&lt;code class=&quot;xml&quot;&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;layout xmlns:android=&amp;quot;http://schemas.android.com/apk/res/android&amp;quot;&amp;gt;
    &amp;lt;data&amp;gt;
        &amp;lt;variable name=&amp;quot;itemVM&amp;quot; type=&amp;quot;com.nilsenlabs.bindingblog.ItemVM&amp;quot; /&amp;gt;
    &amp;lt;/data&amp;gt;
    &amp;lt;TextView
        android:layout_width=&amp;quot;match_parent&amp;quot;
        android:layout_height=&amp;quot;match_parent&amp;quot;
        android:text=&amp;quot;@{itemVM.text}&amp;quot;
        android:textColor=&amp;quot;@{itemVM.color}&amp;quot;&amp;gt;
    &amp;lt;/TextView&amp;gt;
&amp;lt;/layout&amp;gt;
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
&lt;i&gt;Main ViewModel&lt;/i&gt;

&lt;pre&gt;&lt;code class=&quot;kotlin&quot;&gt;
class MainVM {
    val items: ObservableList&lt;ItemVM&gt; = ObservableArrayList()
    val itemBinding: ItemBinding&lt;ItemVM&gt; = ItemBinding.of(BR.itemVM, R.layout.item)

    init {
        items.add(ItemVM(&quot;One&quot;, Color.BLACK))
        items.add(ItemVM(&quot;Two&quot;, Color.GREEN))
    }
}

&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
&lt;i&gt;Item ViewModel&lt;/i&gt;

&lt;pre&gt;&lt;code class=&quot;kotlin&quot;&gt;
class ItemVM(
    val text: String,
    val color: Int
)
&lt;/pre&gt;&lt;/code&gt;

&lt;h2&gt;RadioButtons, CheckBoxes and list of Buttons&lt;/h2&gt;

This one I built myself: I needed to bind a list of RadioButtons to data fetched from a remote service. The number of RadioButtons will vary. A common use case (with or without the service), but not supported out of the box from Google&#39;s Data Binding library. My library, &lt;a href=&quot;https://github.com/Nilzor/bindable-radiobuttons&quot;&gt;bindable-radiobuttons&lt;/A&gt;, also support check boxes, toggle buttons and regular buttons. To produce the screenshot below implement the following:
&lt;p&gt;
&lt;img src=&quot;http://data.nilzorblog.com/blogposts/databinding-filling/radiobuttons.png&quot; width=100 border=1&gt;
&lt;p&gt;
&lt;i&gt;View:&lt;/i&gt;
&lt;pre&gt;&lt;code class=&quot;xml&quot;&gt;
&amp;lt;com.nilsenlabs.bindableradiobuttons.radiobuttons.BindableRadioButtonList
	android:layout_width=&amp;quot;wrap_content&amp;quot;
	android:layout_height=&amp;quot;wrap_content&amp;quot;
	android:orientation=&amp;quot;vertical&amp;quot;
	app:itemViewId=&amp;quot;@layout/my_radio&amp;quot;
	app:selectedItem=&amp;quot;@={viewModel.selectedRadioButton}&amp;quot;
	app:buttons=&amp;quot;@{viewModel.radioButtons}&amp;quot;
	/&amp;gt;
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
&lt;i&gt;ViewModel&lt;/i&gt;
&lt;pre&gt;&lt;code class=&quot;kotlin&quot;&gt;
val radioButtons = listOf(
	RadioButtonViewModel(&quot;One&quot;),
	RadioButtonViewModel(&quot;Two&quot;, isEnabled = false),
	RadioButtonViewModel(&quot;Three&quot;)    
)
val selectedRadioButton = ObservableField&amp;lt;RadioButtonViewModelInterface&amp;gt;(radioButtons[2])
&lt;/pre&gt;&lt;/code&gt;

&lt;h2&gt;Useful Binding Adapters&lt;/h2&gt;

You need a handful of extra &lt;a href=&quot;https://developer.android.com/topic/libraries/data-binding/binding-adapters&quot;&gt;binding adapters&lt;/a&gt; on top of what Google provides to solve a set of common use cases.
&lt;p&gt;
&lt;a href=&quot;https://gist.github.com/Nilzor/13ffe6216b4a444011bee48de5796bce&quot;&gt;Gist with BindingAdapters on Github here&lt;/a&gt;
&lt;p&gt;
&lt;table class=&quot;grid-1&quot;&gt;
&lt;tr&gt;
  &lt;th&gt;Name&lt;th&gt;Input type&lt;th&gt;Binds to&lt;th width=&quot;50%&quot;&gt;Function
&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;app:visibleOrGone&lt;td&gt;Boolean&lt;td&gt;Visiblity&lt;td&gt;true means Visible, false means Gone. My number 1 most used binding adapter.
  &lt;tr&gt;&lt;td&gt;app:visibleOrInvisible&lt;td&gt;Boolean&lt;td&gt;Visiblity&lt;td&gt;true means Visible, false means Invisible
  &lt;tr&gt;&lt;td&gt;app:goneIfNull&lt;td&gt;Any&lt;td&gt;Visiblity&lt;td&gt;null means Gone, non-null means Visible. Perfect if you want a text view to be gone when the String is null.
  &lt;tr&gt;&lt;td&gt;app:onClick&lt;td&gt;None&lt;td&gt;clickListener&lt;td&gt;Just a click listener that doesn&#39;t send &quot;view: View&quot; as unnecessary input parameter
  &lt;tr&gt;&lt;td&gt;android:src&lt;td&gt;Int&lt;td&gt;src&lt;td&gt;Allows you to bind a drawable resources as Int to an ImageView. Google only allows Drawable objects out of the box, which will force you to depend on a Resource object in the VM
  &lt;tr&gt;&lt;td&gt;android:text&lt;td&gt;Int&lt;td&gt;text&lt;td&gt;An improvement to standard TextView text binding that doesn&#39;t crash when the value 0 is bound.
&lt;/tr&gt;  
&lt;/table&gt;  
&lt;/p&gt;
&lt;p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/5160745603183763618/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2022/08/filling-gaps-of-android-databinding.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/5160745603183763618'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/5160745603183763618'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2022/08/filling-gaps-of-android-databinding.html' title='Filling the gaps of Android Databinding'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-6189765701455882021</id><published>2020-04-19T01:28:00.001-07:00</published><updated>2020-04-19T01:30:32.802-07:00</updated><title type='text'>Getting Google Nest Hello Visitor Announcements to Automatically Show on the Google Hub</title><content type='html'>This checklist is for users of the Google Nest Hello connected with Google Nest Hub having trouble&lt;br /&gt;
getting visitor announcements to automatically display on the Hub. It assumes the Hub is properly set up and connected to Google Assistant and Hello so that you can..:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Control the Google Nest Hub from your phone&lt;/li&gt;
&lt;li&gt;See live video stream from your Hello by giving the voice command &quot;&lt;i&gt;Show &amp;lt;Hello_Room_Name&amp;gt;&lt;/i&gt;&quot;&lt;/li&gt;
&lt;/ul&gt;
This checklist should help you solve the final problem:&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;Getting visitor announcements to automatically show on the Google Nest Hub when someone rings the Hello doorbell&lt;/b&gt;&lt;br /&gt;
&lt;h3&gt;
On the Nest Hub device:&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Do not disturb off (center button when swiping up from bottom)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
Google Home app(s):&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on your connected Google Hub Nest Device&lt;/li&gt;
&lt;li&gt;Click settings and ensure:&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Night mode: off&lt;/li&gt;
&lt;li&gt;Recognition and Personalization &amp;gt; Allow Personal results: On&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;div&gt;
If you have multiple accounts associated with the Home make sure you check the settings for all accounts&lt;/div&gt;
&lt;h3&gt;
Nest app:&amp;nbsp;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Settings &amp;gt; Front door &amp;gt; Visitor announcemenbts: On&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
Screenshots:&lt;/h3&gt;
&lt;div&gt;
Google Home, Hub device setup&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnEkyVyqDBV_sNh-CWWbVeXamvK8G0_e0P7O5yrADNqNiJYP1O3aBDDc9PNUvN9dMphAn49Jj_az8qkC1ekwG2JYP5h0YNQ3n-oTzXYRZAYiD-kICxnsHJWmyZ77ydqk1TZyTP89OTLMKe/s1600/recog.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;358&quot; data-original-width=&quot;335&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnEkyVyqDBV_sNh-CWWbVeXamvK8G0_e0P7O5yrADNqNiJYP1O3aBDDc9PNUvN9dMphAn49Jj_az8qkC1ekwG2JYP5h0YNQ3n-oTzXYRZAYiD-kICxnsHJWmyZ77ydqk1TZyTP89OTLMKe/s320/recog.JPG&quot; width=&quot;299&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Google nest:&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhd4xVUmhVS0XdYlpDTrn-vtO90OrXRVPPqccmnLYqzgSdaZ4QeXPB1JROD6wPGK15sG7pAxOp92HKhBx3g5mbMTBAiZErNQdVzVc_sz1WH-cJV4_NBau6sc-SDnVgBJ2bQjNmKHajBSs8c/s1600/nest.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;288&quot; data-original-width=&quot;355&quot; height=&quot;259&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhd4xVUmhVS0XdYlpDTrn-vtO90OrXRVPPqccmnLYqzgSdaZ4QeXPB1JROD6wPGK15sG7pAxOp92HKhBx3g5mbMTBAiZErNQdVzVc_sz1WH-cJV4_NBau6sc-SDnVgBJ2bQjNmKHajBSs8c/s320/nest.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
Other issues:&lt;/h3&gt;
&lt;div&gt;
For other issues some of these guides might help:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://support.google.com/googlenest/answer/7029485&quot;&gt;Official Gogle Nest Hub/Speaker getting started guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://support.google.com/googlenest/answer/9230121?hl=en&quot;&gt;Official Google Nest visistor announcement guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://support.google.com/googlenest/answer/7360025&quot;&gt;Ensure wifi for the Hub correctly set up&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;For more questions visit&amp;nbsp;&lt;a href=&quot;https://support.google.com/googlenest/community?hl=en&quot;&gt;Google nest support community&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/6189765701455882021/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2020/04/getting-google-nest-hello-visitor.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/6189765701455882021'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/6189765701455882021'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2020/04/getting-google-nest-hello-visitor.html' title='Getting Google Nest Hello Visitor Announcements to Automatically Show on the Google Hub'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnEkyVyqDBV_sNh-CWWbVeXamvK8G0_e0P7O5yrADNqNiJYP1O3aBDDc9PNUvN9dMphAn49Jj_az8qkC1ekwG2JYP5h0YNQ3n-oTzXYRZAYiD-kICxnsHJWmyZ77ydqk1TZyTP89OTLMKe/s72-c/recog.JPG" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-1910430587935859764</id><published>2017-05-22T01:00:00.000-07:00</published><updated>2020-07-04T01:58:14.691-07:00</updated><title type='text'>Data Binding with Android Architecture Components Preview</title><content type='html'> &lt;p&gt;In the talk &lt;a href=&quot;https://web.archive.org/web/20180319202301/https://www.youtube.com/watch?v=bEKNi1JOrNs&quot;&gt;Architecture Components – Solving the Lifecycle Problem&lt;/a&gt; from Google I/O 2017, Yigit Boyar talked about the new &lt;code&gt;LiveData&amp;lt;T&amp;gt;&lt;/code&gt; class of the &lt;a href=&quot;https://web.archive.org/web/20180319202301/https://developer.android.com/topic/libraries/architecture/index.html&quot;&gt;Architecture Components library&lt;/a&gt;. When talking about it it’s always coupled with the concept of the &lt;code&gt;ViewModel&lt;/code&gt;. I’ve long been a &lt;a href=&quot;https://web.archive.org/web/20180319202301/http://bytes.schibsted.com/dont-forget-the-view-model/&quot;&gt;fan of the MVVM pattern&lt;/a&gt; when doing mobile development so this was interesting to me. I’ve also been using the &lt;a href=&quot;https://web.archive.org/web/20180319202301/https://developer.android.com/topic/libraries/data-binding/index.html&quot;&gt;Android Databinding&lt;/a&gt; framework, so I was interested in seeing how this plays together.&lt;/p&gt;
&lt;p&gt;tl;dr: Right now, they don’t. But let’s dig a bit deeper.&lt;/p&gt;

&lt;h2&gt;LiveData vs ObservableField&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;LiveData&amp;lt;T&amp;gt;&lt;/code&gt; was presented in a slide as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An Observable data holder&lt;/li&gt;
&lt;li&gt;Lifecycle aware&lt;/li&gt;
&lt;li&gt;Automatic subscription management&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In android data binding we find the sister class &lt;code&gt;ObservableField&amp;lt;T&amp;gt;&lt;/code&gt;. If I were to write a similar slide for that one, it would be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An Observable data holder&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The difference is that &lt;code&gt;ObservableField&amp;lt;T&amp;gt;&lt;/code&gt; isn’t lifecycle-aware and hence there cannot be any automatic subscription management. &lt;em&gt;However&lt;/em&gt; the Android Data Binding framework does the subscription management for you – it’s just not &lt;em&gt;directly&lt;/em&gt; aware of the lifecycle. Instead of immediately unsubscribing when a fragment pauses or stops, it has somewhat of a delay. Notice this memory dump from a bound&amp;nbsp;&lt;code&gt;ObservableField&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;alignleft wp-image-1732107 size-full&quot; src=&quot;http://data.nilzorblog.com/databinding-with-aacp/observablefield.png&quot; alt=&quot;&quot; width=&quot;563&quot; height=&quot;285&quot;&gt;&lt;/p&gt;
&lt;p&gt;You see that the &lt;code&gt;mListener&lt;/code&gt; is a &lt;code&gt;ViewDataBinding$WeakListener&lt;/code&gt;. If you look at the &lt;a href=&quot;https://web.archive.org/web/20180319202301/https://android.googlesource.com/platform/frameworks/data-binding/+/c9a5d6f140f732ca0ff279a4b1ee315072e1c422/library/src/main/java/android/databinding/ViewDataBinding.java#750&quot;&gt;ViewDataBinding class inner workings&lt;/a&gt;, you see that it uses a &lt;a href=&quot;https://web.archive.org/web/20180319202301/https://developer.android.com/reference/java/lang/ref/WeakReference.html&quot;&gt;WeakReference&lt;/a&gt; to the views and view bindings. This ensures that whenever an Activity or Fragment is dead, the reference to the ViewModel and its &lt;code&gt;ObservableFields&lt;/code&gt; are removed in due time. &lt;em&gt;Just not immediately&lt;/em&gt; as you would get if it was lifecycle aware.&lt;/p&gt;

&lt;h2&gt;Using it with data binding&lt;/h2&gt;
&lt;p&gt;So the key question is – can we just swap all usages of &lt;code&gt;Observable&amp;lt;T&amp;gt;&lt;/code&gt; with &lt;code&gt;LiveData&amp;lt;T&amp;gt;&lt;/code&gt; in view models we use with Android Data binding? After all, they’re just observables with life cycle awereness.&lt;/p&gt;
&lt;p&gt;Alas: No.&lt;/p&gt;
&lt;p&gt;In the Android Architecture Components Sample app, it’s implemented rather cumbersome with &lt;a href=&quot;https://web.archive.org/web/20180319202301/https://github.com/googlesamples/android-architecture-components/blob/master/BasicSample/app/src/main/java/com/example/android/persistence/ProductFragment.java#L82&quot;&gt;boilerplate code which pipe data from one type of observables (LiveData) into another (Observable)&lt;/a&gt;. This is why:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;LiveData&amp;lt;T&amp;gt;&lt;/code&gt; cannot be bound to directly in XML.&lt;/li&gt;
&lt;li&gt;The Android Data Binind framework doesn’t know how to &lt;code&gt;observe&lt;/code&gt; on &lt;code&gt;LiveData&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The first bullet point is easily fixable. We could just write &lt;a href=&quot;https://web.archive.org/web/20180319202301/https://github.com/Nilzor/mvp-to-mvvm-transition/blob/androidarch/app/src/main/java/com/nilzor/presenterexample/databinding/LiveDataConverter.java&quot;&gt;a simple converter&lt;/a&gt;. The second one is not as simple though. At least not for us laymen. Google could fix it, and I hope they will. Notice the difference in the interfaces for subscribing on the two classes:

&lt;pre&gt;&lt;code language=&quot;java&quot;&gt;ObservableField.addOnPropertyChangedCallback(Observable.OnPropertyChangedCallback callback);
// versus
LiveData.observe(@NotNullLifecycleOwner owner, Observer observer)
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;You have to provide the &lt;code&gt;LiveData&lt;/code&gt;-object with a &lt;code&gt;LifecycleOwner&lt;/code&gt;. Per now, the Android data binding framework isn’t rigged to do that. But &lt;em&gt;it could be&lt;/em&gt;, and I hope it will be soon. I notice that it’s Yigit Boyar who present these concept – the developer who’s also behind Android Data Binding. He should know how to tie these things together.&lt;/p&gt;
&lt;h2&gt;The ViewModel holder&lt;/h2&gt;
&lt;p&gt;Another interesting class introduced in the Android Architecture Component talks is &lt;code&gt;ViewModelProviders&lt;/code&gt;. I’ve found it does three things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Retains view models across device rotations and other lifecycle-affecting events&lt;/li&gt;
&lt;li&gt;Rids of the view models on &lt;code&gt;onDestroy&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Saves and restores the view models helped by the &lt;code&gt;Parcelable&lt;/code&gt; interface on &lt;code&gt;onSaveInstanceState&lt;/code&gt; and &lt;code&gt;onCreate&lt;/code&gt; *&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*) &lt;em&gt;Disclaimer: Very superficial research done here&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;problem it solves&lt;/strong&gt; is avoiding double calls to expensive services when a long-running request is interrupted by a lifecycle change. Illustrated by this slide in the talk, just to set the context:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://data.nilzorblog.com/databinding-with-aacp/slide.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;I’m claiming that this class bring more value to the table for data binding users than the &lt;code&gt;LiveData&lt;/code&gt;-class. It wasn’t very difficult to achieve before either, though. The Data Binding framework already allowed for this pattern as long as you implemented the holder class yourself.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Example&lt;/em&gt;: I made an improvement to my earlier &lt;a href=&quot;https://web.archive.org/web/20180319202301/https://github.com/Nilzor/mvp-to-mvvm-transition/tree/twoway&quot;&gt;MVVM example project&lt;/a&gt; where I’ve introduced &lt;a href=&quot;https://web.archive.org/web/20180319202301/https://github.com/Nilzor/mvp-to-mvvm-transition/blob/twoway/app/src/main/java/com/nilzor/presenterexample/ViewModelHolder.java&quot;&gt;a holder&lt;/a&gt; for the ViewModel-class accessed through a application-wide singleton. There wasn’t &lt;a href=&quot;https://web.archive.org/web/20180319202301/https://github.com/Nilzor/mvp-to-mvvm-transition/commit/02ccba0e74b970992565bb00b62456a79ee45367&quot;&gt;a lot of code change needed&lt;/a&gt;. You’ll notice after this commit that the “# logged in users” in the top right corner of the example activity doesn’t reset after device rotation using this technique – even if you interrupt the 2 second long initial load.&lt;/p&gt;
&lt;p&gt;In the branch &lt;a href=&quot;https://web.archive.org/web/20180319202301/https://github.com/Nilzor/mvp-to-mvvm-transition/tree/androidarch&quot;&gt;androidarch&lt;/a&gt; I solved the same problem using the &lt;code&gt;ViewModelProviders&lt;/code&gt;-class from the Architecture Components. I also experimented with binding to a &lt;code&gt;LiveData&lt;/code&gt; class instead of &lt;code&gt;ObservableField&lt;/code&gt;, but found it not to bring any value to the architecture or solution due the arguments stated above.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I think the Android Architecture Components is a good set of components that for sure will make it easier for new developers to create a solid foundation from the start. The earlier examples from Google have rieked of bad practices and been riddled with pitfalls. But in terms of the interoperability with Android Databinding it seems very unfinished. Maybe they hoped to get it more done for Google I/O than what was presented. In any case I look forward to the next versions of this library and its migration into the support framework.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/1910430587935859764/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2017/05/data-binding-with-android-architecture.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/1910430587935859764'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/1910430587935859764'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2017/05/data-binding-with-android-architecture.html' title='Data Binding with Android Architecture Components Preview'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-7943327124976204701</id><published>2016-10-16T01:43:00.000-07:00</published><updated>2020-07-04T01:44:15.666-07:00</updated><title type='text'>Two way data binding without RxJava</title><content type='html'>&lt;p&gt;A couple of weeks ago, &lt;a href=&quot;https://web.archive.org/web/20181112212526/https://medium.com/tangoagency/rxjava-meets-android-data-binding-4ca5e1144107#.dbcoc8tb6&quot;&gt;this article&lt;/a&gt;&amp;nbsp;by&amp;nbsp;Radosław Piekarz got some tracktion on &lt;a href=&quot;https://web.archive.org/web/20181112212526/https://www.reddit.com/r/androiddev/comments/55nl2f/rxjava_meets_android_data_binding/&quot;&gt;/r/androiddev&lt;/a&gt;. While I am a fan of RxJava myself we use it extensively in our&amp;nbsp;apps at &lt;a href=&quot;https://web.archive.org/web/20181112212526/http://www.vg.no/&quot;&gt;VG.no&lt;/a&gt;, I feel this example was not the best use case for it. As others point out in the comment field, this can easily be solved without RxJava.&amp;nbsp;Here is how:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;java&quot;&gt;
public MainViewModel() {
    OnPropertyChangedCallback buttonUpdater = new OnPropertyChangedCallback() {
        @Override
        public void onPropertyChanged(Observable sender, int propertyId) {
            updateButtonEnabledState();
        };
    };
    firstName.addOnPropertyChangedCallback(buttonUpdater);
    lastName.addOnPropertyChangedCallback(buttonUpdater);
}

private void updateButtonEnabledState() {
    boolean enable = StringUtils.isNotNullOrEmpty(firstName.get()) &amp;amp;amp;&amp;amp;amp; StringUtils.isNotNullOrEmpty(lastName.get());
    helloButtonEnabled.set(enable);
}
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;What I’ve done is recoded the constructor of the viewmodel for MainActivity to hook onto the &lt;code&gt;OnPropertyChanged&lt;/code&gt; callback of the ObservableFields for the two TextViews directly, instead of going through the hoop of &lt;code&gt;RxUtils.toObservable&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can furthermore clean up the code by writing an adapter for the OnPropertyChanged callback, which as it is is not very lambda-friendly. Introducing the helper class &lt;code&gt;BindingCallbackAdapter&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;java&quot;&gt;
public class BindingCallbackAdapter extends Observable.OnPropertyChangedCallback {
    private Callback mCallback;

    public BindingCallbackAdapter(BindingCallbackAdapter.Callback callback) {
        if (callback == null) throw new IllegalArgumentException(&quot;Callback cannot be null&quot;);
        mCallback = callback;
    }

    @Override
    public void onPropertyChanged(Observable sender, int propertyId) {
        mCallback.onChanged();
    }

    public interface Callback {
        void onChanged();
    }
}
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;..and the more readable&amp;nbsp;MainActivity-constructor:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;java&quot;&gt;
public MainViewModel() {
    OnPropertyChangedCallback buttonUpdater = new BindingCallbackAdapter(this::updateButtonEnabledState);
    firstName.addOnPropertyChangedCallback(buttonUpdater);
    lastName.addOnPropertyChangedCallback(buttonUpdater);
}
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;See full fork&amp;nbsp;&lt;a href=&quot;https://web.archive.org/web/20181112212526/https://github.com/Nilzor/android-data-binding-rxjava&quot;&gt;at github.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;While I’m sure the author of the original article is aware of the&amp;nbsp;possibility of this implementation, I’m afraid that too many blog posts about “RxJava for everything” spreads antipatterns.&amp;nbsp;I do understand that there are cases where this &lt;em&gt;could&lt;/em&gt; be a good pattern, for example if you need to compose the &lt;code&gt;onPropertyChanged&lt;/code&gt; events in more complex Rx-flows, but this concrete use case is not one.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/7943327124976204701/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2016/10/two-way-data-binding-without-rxjava.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/7943327124976204701'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/7943327124976204701'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2016/10/two-way-data-binding-without-rxjava.html' title='Two way data binding without RxJava'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-6534369600254408120</id><published>2016-08-13T10:23:00.002-07:00</published><updated>2017-02-18T02:05:37.231-08:00</updated><title type='text'>Async programming patterns in different languages</title><content type='html'>During the 10 years I&#39;ve been into professional programming, the largest paradigm shift I&#39;ve witnessed is the one from sequential to asynchronous programming. Not that it is a new concept - asynchronousity has been has been present in programming since the dawn of time, but what&#39;s new is the tight integration in programming languages and the prevalence of it. From events and callbacks in C# to &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/mt674882.aspx&quot;&gt;async-await&lt;/a&gt;. From callbacks in Javascript to &lt;a href=&quot;https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise&quot;&gt;Promises&lt;/a&gt;. In Java we got &lt;a href=&quot;https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html&quot;&gt;Futures&lt;/a&gt; in Java 7, &lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html&quot;&gt;CompletableFuture&lt;/a&gt;, lambdas and streams in Java 8. On top of all these language features you have a vast array of libraries that help you implement common async patterns - &lt;a href=&quot;http://reactivex.io/&quot;&gt;ReactiveX&lt;/a&gt; for instance exists for all the three languages mentioned, and a lot more.

I&#39;ve been programming quite a bit in all the three languages mentioned: C#, Java and Javascript, and I realized I had to re-learn all the same patterns over and over again. On top of the languages features there were libraries as well. Multiple for each language. In this blog post I will iterate what I believe are the 3 most common patterns, list and compare them in these languages. I welcome contributions for other languages or patterns to this &lt;a href=&quot;https://github.com/Nilzor/multilanguage-async-patterns&quot;&gt;github repo&lt;/a&gt; - let&#39;s together make this more a reference than a blog post!

The patterns I most often use are the following: serial execution, parallel execution where you must wait for all to complete, and parallel execution where you just want the first result to return. I&#39;m also most often using these pattern in relation to network transfers (HTTP). So first I will illustrate the three patterns with different use cases:
&lt;h3&gt;
Use case 1: Serial execution of HTTP calls&lt;/h3&gt;
Let&#39;s say you&#39;re building a user interface which depends on two REST services. One provide a list of news article items, while the other is an image hosting service which return image binaries from URL&#39;s. The first service returns URL&#39;s which are to be used as input for the second service. This makes second operation dependent on the first - they have to be executed serially:

&lt;img alt=&quot;Serial execution&quot; src=&quot;http://Data.nilzorblog.com/blogposts/async-patterns/async-1.png&quot; style=&quot;display:block&quot; /&gt;
&lt;h3&gt;
Use case 2: Parallel execution, wait for all&lt;/h3&gt;
This time the user interface is composed of data from two independent services. You want to display a blank screen with a progress bar only while loading. Only when all data is fetched, you start rendering. This is what I dub the form-merge parallel execution:

&lt;img alt=&quot;Fork-merge parallel&quot;  src=&quot;http://Data.nilzorblog.com/blogposts/async-patterns/async-2.png&quot; style=&quot;display:block&quot; /&gt;
&lt;h3&gt;
Use case 3: Parallel execution, take first&lt;/h3&gt;
In this case you&#39;re firing multiple HTTP queries to identical services, but only care for the response from the first to reply. It might be that you&#39;re building a performance-critical application, or you have multiple 3rd-party providers delivering the same service but with varying degree of reliability.

&lt;img alt=&quot;Take first parallel&quot; src=&quot;http://Data.nilzorblog.com/blogposts/async-patterns/async-3.png&quot; style=&quot;display:block&quot; /&gt;
&lt;h2&gt;
Implementation&lt;/h2&gt;
Below is listed short examples illustrating the three patterns in the different languages, with support functions in the first chapter.

For Java I&#39;ve chosen to use the &lt;a href=&quot;https://github.com/ReactiveX/RxJava&quot;&gt;RxJava&lt;/a&gt; framework simply because that&#39;s what I know best. If you know how to do the same with plain Java (8), please let me know or contribute with a pull request to &lt;a href=&quot;https://github.com/Nilzor/multilanguage-async-patterns&quot;&gt;the repo&lt;/a&gt;!

&lt;!-- CODE BEGIN --&gt;

&lt;!-- PATTERN START: ---&gt;
&lt;p&gt;&lt;h3 style=&#39;display:inline-block&#39;&gt;Support functions&lt;/h3&gt;
&lt;div class=&quot;tabbed&quot;&gt;            &lt;input name=&#39;group1&#39; id=&#39;tabbed1&#39; type=&#39;radio&#39; checked&gt;
            &lt;section&gt;
                &lt;h5&gt;&lt;label for=&#39;tabbed1&#39;&gt;Javascript / ES6-Promise&lt;/label&gt;&lt;/h5&gt;
                &lt;div&gt;
                    &lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;// Resolves the input value after 300ms
function getSlowPromise(returnValue) {
    return new Promise((resolve) =&amp;gt; {
        setTimeout(() =&amp;gt; {
            resolve(returnValue);
        }, 300);
    });
}&lt;/code&gt;&lt;/pre&gt;
                &lt;/div&gt;
            &lt;/section&gt;
                    &lt;input name=&#39;group1&#39; id=&#39;tabbed3&#39; type=&#39;radio&#39; &gt;
            &lt;section&gt;
                &lt;h5&gt;&lt;label for=&#39;tabbed3&#39;&gt;C#&lt;/label&gt;&lt;/h5&gt;
                &lt;div&gt;
                    &lt;pre&gt;&lt;code class=&quot;csharp&quot;&gt;// Returns input string after 250ms
public static async Task&amp;lt;string&amp;gt; GetSlowStringTask(String toReturn)
{
    await Task.Delay(250);
    return toReturn;
}

// Returns input int after 250ms
public static async Task&amp;lt;int&amp;gt; GetSlowIntTask(int toReturn)
{
    await Task.Delay(250);
    return toReturn;
}&lt;/code&gt;&lt;/pre&gt;
                &lt;/div&gt;
            &lt;/section&gt;
                    &lt;input name=&#39;group1&#39; id=&#39;tabbed4&#39; type=&#39;radio&#39; &gt;
            &lt;section&gt;
                &lt;h5&gt;&lt;label for=&#39;tabbed4&#39;&gt;Kotlin&lt;/label&gt;&lt;/h5&gt;
                &lt;div&gt;
                    &lt;pre&gt;&lt;code class=&quot;kotlin&quot;&gt;suspend fun getSlowStringJob(s: String) : String {
    delay(250)
    return s
}

suspend fun getSlowIntJob(i: Int) : Int {
    delay(250)
    return i
}

// Returns the deferred job which completes first
suspend fun &amp;lt;T&amp;gt; awaitFirst(jobs : Array&amp;lt;Deferred&amp;lt;T&amp;gt;&amp;gt;) : Deferred&amp;lt;T&amp;gt; {
    var doneJob : Deferred&amp;lt;T&amp;gt;? = null
    while (doneJob == null) {
        for (job in jobs) {
            if (job.isCompleted) {
                doneJob = job
                break;
            }
            yield()
        }
    }
    return doneJob
}&lt;/code&gt;&lt;/pre&gt;
                &lt;/div&gt;
            &lt;/section&gt;
        &lt;/div&gt;&lt;/p&gt;
&lt;!-- PATTERN START: ---&gt;
&lt;p&gt;&lt;h3 style=&#39;display:inline-block&#39;&gt;Pipeline / Serial execution&lt;/h3&gt;
&lt;div class=&quot;tabbed&quot;&gt;            &lt;input name=&#39;group2&#39; id=&#39;tabbed5&#39; type=&#39;radio&#39; checked&gt;
            &lt;section&gt;
                &lt;h5&gt;&lt;label for=&#39;tabbed5&#39;&gt;Javascript / ES6-Promise&lt;/label&gt;&lt;/h5&gt;
                &lt;div&gt;
                    &lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;// createPromise is a method returning a promise which resolves to the input value
getSlowPromise(&#39;job1&#39;)
    .then((result) =&amp;gt; {
        return getSlowPromise(result + &#39;-job2&#39;);
    }).then((result) =&amp;gt; {
        return getSlowPromise(result + &#39;-job3&#39;);
    }).then((result) =&amp;gt; {
        // Result from third job
    });&lt;/code&gt;&lt;/pre&gt;
                &lt;/div&gt;
            &lt;/section&gt;
                    &lt;input name=&#39;group2&#39; id=&#39;tabbed6&#39; type=&#39;radio&#39; &gt;
            &lt;section&gt;
                &lt;h5&gt;&lt;label for=&#39;tabbed6&#39;&gt;Java / RxJava&lt;/label&gt;&lt;/h5&gt;
                &lt;div&gt;
                    &lt;pre&gt;&lt;code class=&quot;java&quot;&gt;Observable&amp;lt;String&amp;gt; obs1 = Observable.just(&quot;Hello world&quot;);
obs1.flatMap(s -&amp;gt; {
    Observable&amp;lt;Integer&amp;gt; obs2 =  Observable.just(s.length());
    return obs2;
}).flatMap(i -&amp;gt; {
    Observable&amp;lt;String&amp;gt; obs3 = Observable.just(&quot;Length: &quot; + i);
    return obs3;
}).subscribe(s -&amp;gt;{
    System.out.println(s);
    // Will output &quot;Length: 11&quot;
});

&lt;/code&gt;&lt;/pre&gt;
                &lt;/div&gt;
            &lt;/section&gt;
                    &lt;input name=&#39;group2&#39; id=&#39;tabbed7&#39; type=&#39;radio&#39; &gt;
            &lt;section&gt;
                &lt;h5&gt;&lt;label for=&#39;tabbed7&#39;&gt;C#&lt;/label&gt;&lt;/h5&gt;
                &lt;div&gt;
                    &lt;pre&gt;&lt;code class=&quot;csharp&quot;&gt;var str = await GetSlowStringTask(&quot;Hello world&quot;);
var len = await GetSlowIntTask(str.Length);
var res = await GetSlowStringTask(&quot;Len: &quot; + len);
Console.Out.WriteLine(res);&lt;/code&gt;&lt;/pre&gt;
                &lt;/div&gt;
            &lt;/section&gt;
                    &lt;input name=&#39;group2&#39; id=&#39;tabbed8&#39; type=&#39;radio&#39; &gt;
            &lt;section&gt;
                &lt;h5&gt;&lt;label for=&#39;tabbed8&#39;&gt;Kotlin&lt;/label&gt;&lt;/h5&gt;
                &lt;div&gt;
                    &lt;pre&gt;&lt;code class=&quot;kotlin&quot;&gt;launch(CommonPool) {
    val res1 = getSlowStringJob(&quot;Hello&quot;)
    val res2 = getSlowIntJob(res1.length)
    val res3 = getSlowStringJob(&quot;First string length: &quot; + res2)
    System.out.println(res3)
}&lt;/code&gt;&lt;/pre&gt;
                &lt;/div&gt;
            &lt;/section&gt;
        &lt;/div&gt;&lt;/p&gt;
&lt;!-- PATTERN START: ---&gt;
&lt;p&gt;&lt;h3 style=&#39;display:inline-block&#39;&gt;Parallel fork-join&lt;/h3&gt;
&lt;div class=&quot;tabbed&quot;&gt;            &lt;input name=&#39;group3&#39; id=&#39;tabbed9&#39; type=&#39;radio&#39; checked&gt;
            &lt;section&gt;
                &lt;h5&gt;&lt;label for=&#39;tabbed9&#39;&gt;Javascript / ES6-Promise&lt;/label&gt;&lt;/h5&gt;
                &lt;div&gt;
                    &lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;// Assuming promise1, 2 and 3 are created
// before this code executing
Promise.all([
    promise1,
    promise2,
    promise3
]).then((results) =&amp;gt; {
    // &#39;results&#39; is array of results from each promise
})&lt;/code&gt;&lt;/pre&gt;
                &lt;/div&gt;
            &lt;/section&gt;
                    &lt;input name=&#39;group3&#39; id=&#39;tabbed10&#39; type=&#39;radio&#39; &gt;
            &lt;section&gt;
                &lt;h5&gt;&lt;label for=&#39;tabbed10&#39;&gt;Java / RxJava&lt;/label&gt;&lt;/h5&gt;
                &lt;div&gt;
                    &lt;pre&gt;&lt;code class=&quot;java&quot;&gt;// obs1, 2 and 3 are Observable&amp;lt;String&amp;gt;&#39;s
// Assuming each observable only emits 1 value
obs1.mergeWith(obs2)
    .mergeWith(obs3)
    .buffer(3)
    .subscribe(resultArray -&amp;gt; {
        // resultArray is String[3]
    });
&lt;/code&gt;&lt;/pre&gt;
                &lt;/div&gt;
            &lt;/section&gt;
                    &lt;input name=&#39;group3&#39; id=&#39;tabbed11&#39; type=&#39;radio&#39; &gt;
            &lt;section&gt;
                &lt;h5&gt;&lt;label for=&#39;tabbed11&#39;&gt;C#&lt;/label&gt;&lt;/h5&gt;
                &lt;div&gt;
                    &lt;pre&gt;&lt;code class=&quot;csharp&quot;&gt;var tasks = new Task&amp;lt;int&amp;gt;[3];
tasks[0] = GetSlowIntTask(1);
tasks[1] = GetSlowIntTask(2);
tasks[2] = GetSlowIntTask(3);
Task.WaitAll(tasks);
for (int i = 0; i &amp;lt; 3; i++)
{
    Console.Out.WriteLine(&quot;Res &quot; + i + &quot;: &quot; + tasks[i].Result);
}&lt;/code&gt;&lt;/pre&gt;
                &lt;/div&gt;
            &lt;/section&gt;
                    &lt;input name=&#39;group3&#39; id=&#39;tabbed12&#39; type=&#39;radio&#39; &gt;
            &lt;section&gt;
                &lt;h5&gt;&lt;label for=&#39;tabbed12&#39;&gt;Kotlin&lt;/label&gt;&lt;/h5&gt;
                &lt;div&gt;
                    &lt;pre&gt;&lt;code class=&quot;kotlin&quot;&gt;val job1 = async(CommonPool) { getSlowIntJob(1) }
val job2 = async(CommonPool) { getSlowIntJob(2) }
val job3 = async(CommonPool) { getSlowIntJob(3) }
launch(CommonPool) {
    val sum = job1.await() + job2.await() + job3.await()
    System.out.println(&quot;Sum: &quot; + sum)
}&lt;/code&gt;&lt;/pre&gt;
                &lt;/div&gt;
            &lt;/section&gt;
        &lt;/div&gt;&lt;/p&gt;
&lt;!-- PATTERN START: ---&gt;
&lt;p&gt;&lt;h3 style=&#39;display:inline-block&#39;&gt;Parallel take first&lt;/h3&gt;
&lt;div class=&quot;tabbed&quot;&gt;            &lt;input name=&#39;group4&#39; id=&#39;tabbed13&#39; type=&#39;radio&#39; checked&gt;
            &lt;section&gt;
                &lt;h5&gt;&lt;label for=&#39;tabbed13&#39;&gt;Javascript / ES6-Promise&lt;/label&gt;&lt;/h5&gt;
                &lt;div&gt;
                    &lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;Promise.race([
    promise1,
    promise2,
    promise3
]).then((result) =&amp;gt; {
    // result is first to return
})&lt;/code&gt;&lt;/pre&gt;
                &lt;/div&gt;
            &lt;/section&gt;
                    &lt;input name=&#39;group4&#39; id=&#39;tabbed14&#39; type=&#39;radio&#39; &gt;
            &lt;section&gt;
                &lt;h5&gt;&lt;label for=&#39;tabbed14&#39;&gt;Java / RxJava&lt;/label&gt;&lt;/h5&gt;
                &lt;div&gt;
                    &lt;pre&gt;&lt;code class=&quot;java&quot;&gt;// obs1, 2 and 3 are Observable&amp;lt;String&amp;gt;&#39;s
// Assuming each observable only emits 1 value
obs1.mergeWith(obs2)
    .mergeWith(obs3)
    .first()
    .subscribe(result -&amp;gt; {
        // result is String
    });
&lt;/code&gt;&lt;/pre&gt;
                &lt;/div&gt;
            &lt;/section&gt;
                    &lt;input name=&#39;group4&#39; id=&#39;tabbed15&#39; type=&#39;radio&#39; &gt;
            &lt;section&gt;
                &lt;h5&gt;&lt;label for=&#39;tabbed15&#39;&gt;C#&lt;/label&gt;&lt;/h5&gt;
                &lt;div&gt;
                    &lt;pre&gt;&lt;code class=&quot;csharp&quot;&gt;var tasks = new Task&amp;lt;int&amp;gt;[3];
tasks[0] = GetSlowIntTask(1);
tasks[1] = GetSlowIntTask(2);
tasks[2] = GetSlowIntTask(3);
int firstResult = Task.WaitAny(tasks);
Console.Out.WriteLine(&quot;Res &quot; + firstResult);&lt;/code&gt;&lt;/pre&gt;
                &lt;/div&gt;
            &lt;/section&gt;
                    &lt;input name=&#39;group4&#39; id=&#39;tabbed16&#39; type=&#39;radio&#39; &gt;
            &lt;section&gt;
                &lt;h5&gt;&lt;label for=&#39;tabbed16&#39;&gt;Kotlin&lt;/label&gt;&lt;/h5&gt;
                &lt;div&gt;
                    &lt;pre&gt;&lt;code class=&quot;kotlin&quot;&gt;val job1 = async(CommonPool) { getSlowIntJob(1) }
val job2 = async(CommonPool) { getSlowIntJob(2) }
val job3 = async(CommonPool) { getSlowIntJob(3) }
launch(CommonPool) {
    val jobs = arrayOf(job1, job2, job3)
    val first = awaitFirst(jobs)
    System.out.println(&quot;Finished first: &quot; + first.getCompleted())
}&lt;/code&gt;&lt;/pre&gt;
                &lt;/div&gt;
            &lt;/section&gt;
        &lt;/div&gt;&lt;/p&gt;

&lt;!-- CODE END --&gt;     
&lt;p&gt;Thanks to Espen Volden for contributing with Javascript examples &lt;/p&gt;
&lt;p&gt;
&lt;i&gt;Article updated 18 Feb 2017 with Kotlin 1.1 Coroutines examples&lt;/i&gt;
 &lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/6534369600254408120/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2016/08/async-programming-patterns-in-different_82.html#comment-form' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/6534369600254408120'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/6534369600254408120'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2016/08/async-programming-patterns-in-different_82.html' title='Async programming patterns in different languages'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-8752730961904667880</id><published>2015-07-17T05:07:00.000-07:00</published><updated>2015-07-17T05:07:24.260-07:00</updated><title type='text'>Android Data Binding: Goodbye Presenter, Hello ViewModel!</title><content type='html'>The &lt;a href=&quot;https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter&quot;&gt;Model-View-Presenter-pattern&lt;/a&gt; (MVP) has been the dominating trend lately when it comes the UI-layer architecture of Android applications. Frameworks like &lt;a href=&quot;http://hannesdorfmann.com/android/mosby/&quot;&gt;Ted Mosby&lt;/a&gt;, &lt;a href=&quot;https://github.com/konmik/nucleus&quot;&gt;Nucleus&lt;/a&gt; and &lt;a href=&quot;https://github.com/square/mortar&quot;&gt;Mortar&lt;/a&gt; have all talked about Presenters to help you achieving a clean architecture of your app. They also (to a variyng degree) help you with the infamous issues of device rotation and state persistence on the Android platform. This isn&#39;t directly related to the concept of MVP, but the pattern helps you isolate the boiler plate code.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://developer.android.com/tools/data-binding/guide.html&quot;&gt;Data binding&lt;/a&gt;, as announced on Google I/O 2015 and introduced in the Android M preview, changes everything. According to the Wikipedia article on MVP, the Presenter has the following tasks:&lt;br /&gt;
&lt;blockquote&gt;The presenter acts upon the model and the view. It retrieves data from repositories (the model), and formats it for display in the view.&lt;/blockquote&gt;The thing is that Data Binding framework will take over the main responsibilities of the Presenter (&quot;acting upon the model and the view&quot;), while the remainder is left to the enhanced Model - the &lt;em&gt;ViewModel&lt;/em&gt; (&quot;retreiving data from repositories and formatting&quot;). The ViewModel is a standard Java class whose sole responsibility is to represent the data behind a single View. It can merge data from multiple sources (Models) and prepare that data for presentation. I did &lt;a href=&quot;http://tech.vg.no/2015/04/06/dont-forget-the-view-model/&quot;&gt;a short writeup&lt;/a&gt; on the ViewModel and how it differs from Data Model or Transport Model. &lt;br /&gt;
&lt;br /&gt;
The architecture we end up with is MVVM - &lt;a href=&quot;https://en.wikipedia.org/wiki/Model_View_ViewModel&quot;&gt;Model-View-ViewModel&lt;/a&gt;, and is a proven concept originally coined by Microsoft back in 2005 (don&#39;t let that scare you ;-) ). Let me illustrate the change from MVP to MVVM for you, shamelessly copying Hanne Dorfmann&#39;s illustration from the &lt;a href=&quot;http://hannesdorfmann.com/android/mosby&quot;&gt;introduction of his Ted Mosby framework&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://tech.vg.no/files/2015/07/mvp.png&quot;&gt;&lt;img class=&quot;alignnone size-medium wp-image-3596&quot; src=&quot;https://tech.vg.no/files/2015/07/mvp.png&quot; alt=&quot;mvp&quot; width=&quot;500&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://tech.vg.no/files/2015/07/mvvm.png&quot;&gt;&lt;img class=&quot;alignnone size-medium wp-image-3597&quot; src=&quot;https://tech.vg.no/files/2015/07/mvvm.png&quot; alt=&quot;mvvm&quot; width=&quot;500&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
So all the binding and updating of data to the view is done through the Data Binding Framework. The &lt;a href=&quot;https://developer.android.com/tools/data-binding/guide.html#observablefields&quot;&gt;ObservableField&lt;/a&gt; class allow the View to react on changes to the model, and the XML references to fields allow the framework to push changes back to the ViewModel when the user acts upon the View. You can also programatically subscribe to changes in fields so that for instance a &lt;code&gt;TextView&lt;/code&gt; is disabled when a &lt;code&gt;CheckBox&lt;/code&gt; is clicked. One great advantage of representing the visual state of the View in a standard Java class like this is clear: You can easily unit test the visual behaviour.&lt;br /&gt;
&lt;br /&gt;
Note that in the MVP illustration above there is a method call to &lt;code&gt;Presenter.loadUsers()&lt;/code&gt;. This is a &lt;em&gt;Command&lt;/em&gt;. In MVVM these are methods defined in the ViewModel. From the Wikipedia article:&lt;br /&gt;
&lt;blockquote&gt;The view model is an abstraction of the view that exposes public properties and &lt;em&gt;commands&lt;/em&gt;&lt;/blockquote&gt;So this may or may not be a change to what you&#39;re used to. In the MVP pattern it&#39;s likely that your models were &quot;dumb&quot; classes only holding data. Don&#39;t be afraid of putting business logic in your Models or View Models as well. This is a core principle of &lt;a href=&quot;https://en.wikipedia.org/wiki/Object-oriented_programming&quot;&gt;Object Oriented Programming&lt;/a&gt;. So back to &lt;code&gt;Presenter.loadUsers()&lt;/code&gt; - this will now be a method in the ViewModel and may be invoked programmatically by the code-behind* of your View or though a data bound &lt;em&gt;command&lt;/em&gt; in the XML of your View. That is - if the promises of &lt;a href=&quot;https://code.google.com/p/android-developer-preview/issues/detail?id=2097&quot;&gt;this issue&lt;/a&gt; in the android-developer-preview issue tracker hold up. If we don&#39;t get data binding to commands, we have to resort to the old &lt;code&gt;android:onClick&lt;/code&gt;-syntax, or manually adding listeners in the View code as before.&lt;br /&gt;
&lt;br /&gt;
&lt;p style=&quot;padding-left: 30px;font-size: 80%&quot;&gt;*) &quot;Code-behind&quot; is a term from Microsoft, often with negative associations to early ASP.NET or WinForms. I think it&#39;s a describing term also on Android where the View is composed of two source elements: the View Layout (XML) and the Code-Behind (Java), represented by Fragments, Activities and classes extending View.java.&lt;/p&gt;&lt;h2 id=&quot;dealing-with-system-calls&quot;&gt;Dealing with system calls&lt;/h2&gt;There is one set of use cases which still have to be done in the code-behind of the View - functions which initate system calls, opens dialogs or basically any call which require reference the &lt;code&gt;Context&lt;/code&gt; object of Android. Don&#39;t put code like this in the ViewModel. If it contains the line &lt;code&gt;import android.content.Context;&lt;/code&gt;, you&#39;re doing it wrong. Don&#39;t do it. Kittens die.&lt;br /&gt;
&lt;br /&gt;
I haven&#39;t quite made up my mind on the best approach to tackle this yet, but that&#39;s because there are several good options. One way would be to keep elements of the presenter concept from Mosby by referencing an interface to the View in the ViewModel. This way you won&#39;t reduce the testability. But instead of having a seperate Presenter class as in Mosby, I&#39;d stick to the View as the concrete implementation of that interface just to keep it simple. Another approach could be to use an event bus like &lt;a href=&quot;http://square.github.io/otto/&quot;&gt;Square&#39;s Otto&lt;/a&gt; to initiate commands like &lt;code&gt;new ShowToastMessage(&quot;hello world&quot;)&lt;/code&gt;. This will yield a greater separation of the view and the viewmodel - but is that a good thing?&lt;br /&gt;
&lt;h2 id=&quot;don-t-we-need-frameworks-now-&quot;&gt;Don&#39;t we need frameworks now?&lt;/h2&gt;So is the Data Binding framework taking over the job of framworks like Mosby or Mortar? Only partly. What I hope to see is these frameworks evolve or fork into MVVM-style frameworks so that we can leverage the best of Data Binding while keeping the dependencies to 3rd-party frameworks to a minimum, and keeping the frameworks small and simple. While the era of the Presenter might be over, the framworks do a just as important job with lifecycle management and view state (ViewModel) persistence. This has not changed (unfortunately*)&lt;br /&gt;
&lt;br /&gt;
&lt;p style=&quot;padding-left: 30px;font-size: 80%&quot;&gt;*) Wouldn&#39;t it be cool if Google introduced an interface &lt;code&gt;LifeCycleAffected&lt;/code&gt; which &lt;code&gt;Fragment&lt;/code&gt;, &lt;code&gt;Activity&lt;/code&gt; and &lt;code&gt;View&lt;/code&gt; implemented? And that interface had methods named &lt;code&gt;addOnPauseListener()&lt;/code&gt; and &lt;code&gt;addOnResumeListener()&lt;/code&gt;? I leave it up to you to what that might have done with our code base, and the code base of MVP/MVVM frameworks.&lt;/p&gt;&lt;br /&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;When I first heard that Android M was all about improving the SDK and focusing on the developers, I was really excited. When I heard they were introducing Data Binding, I was stoked. I have worked for years with data binding on other platforms : WinForms, WPF, Silverlight and Windows Phone. I &lt;em&gt;know&lt;/em&gt; it will help us write cleaner architecture and less boiler plate code. The framework works &lt;em&gt;with us&lt;/em&gt; instead of against us, as I&#39;ve felt it has been for a long time. &lt;br /&gt;
&lt;br /&gt;
But it&#39;s not a silver bullet - there are downsides. The fact that you define stuff in XML is an issue. XML is not compiled. XML cannot be unit tested. Hence you&#39;ll often end up noticing errors run-time instead of compile time. Forgot to bind the field to the view? Tough luck. But the tooling can help a great deal here - that&#39;s why I hope Google is focusing &lt;em&gt;hard&lt;/em&gt; on making Android Studio support data binding to the max. Syntax and reference checking of the binding XML, auto complete and navigation support. Field renaming support which propagates to XML. From my testing of Android Studio 1.3 beta - I&#39;m at least assured that the &lt;em&gt;are&lt;/em&gt; thinking about it. Some things are supported. A lot isn&#39;t, but we&#39;re still in beta so here&#39;s hoping.&lt;br /&gt;
&lt;br /&gt;
&lt;h2 id=&quot;code example&quot;&gt;Code example&lt;/h2&gt;I&#39;ve posted an example &lt;a href=&quot;https://github.com/Nilzor/mvp-to-mvvm-transition&quot;&gt;on github&lt;/a&gt; where I try to illustrate the conseqeunces of going from MVP to an MVVM architecture. I used Mosby as a framework in the MVP version with Butterknife for view injection. In the MVVM example I&#39;m using Android M databinding and drop dependencis to both Mosby and Butterknife. The result is that the Presenter can be dropped, the Fragment gets less code but the ViewModel takes over a lot of the code. In some sense it actually acts partly as a presenter, in that it directly or indirectly notifies the view.&lt;br /&gt;
&lt;br /&gt;
The example is a login screen with som async data loading and inter-view dependencies just for illustration purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://tech.vg.no/files/2015/07/illustration.png&quot;&gt;&lt;img src=&quot;https://tech.vg.no/files/2015/07/illustration-266x300.png&quot; alt=&quot;illustration&quot; width=&quot;266&quot; height=&quot;300&quot; class=&quot;alignnone size-medium wp-image-3620&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Checkout the &lt;a href=&quot;https://github.com/Nilzor/mvp-to-mvvm-transition/tree/mvp&quot;&gt;MVP tag&lt;/a&gt; to see the MVP example and the &lt;a href=&quot;https://github.com/Nilzor/mvp-to-mvvm-transition/tree/mvvm&quot;&gt;MVVM&lt;/a&gt; for Databound MVVM</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/8752730961904667880/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2015/07/android-databinding-goodbye-presenter.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/8752730961904667880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/8752730961904667880'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2015/07/android-databinding-goodbye-presenter.html' title='Android Data Binding: Goodbye Presenter, Hello ViewModel!'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-3703313121211990685</id><published>2015-04-07T01:13:00.001-07:00</published><updated>2015-04-07T02:27:36.272-07:00</updated><title type='text'>Don&#39;t forget the View Model!</title><content type='html'>&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;I&#39;ve observed an increase in architecture-focused Android posts lately in channels such as &lt;a href=&quot;http://www.reddit.com/r/androiddev&quot;&gt;/r/androiddev&lt;/a&gt; and &lt;a href=&quot;http://androidweekly.net/&quot;&gt;Android Weekly&lt;/a&gt;. That&#39;s great, but frankly it&#39;s about time. When I transitioned from Windows Phone development to Android a couple of years ago I felt it was difficult to find good examples on how to architect a solid app. It didn&#39;t help that Google&#39;s examples violated most best practices[1] either. I kind of went with my own version of &lt;a href=&quot;http://en.wikipedia.org/wiki/Model_View_ViewModel&quot;&gt;MVVM&lt;/a&gt; (or MVPVM) which I had with me from the .NET platform and it sort of worked. Reading&lt;br /&gt;
Hannes Dorfmann&#39;s post &lt;a href=&quot;hannesdorfmann.coandm/android/mosby/&quot;&gt;on MVP and his Mosby framework&lt;/a&gt;, I realize I&#39;m not the only one who&#39;ve been struggling with getting the established patterns working with Android (he spent 3 years). The framework is not exactly leading you into a good architecture. Maybe Fragments is partly to blame, and why Square Inc is &lt;a href=&quot;https://corner.squareup.com/2014/10/advocating-against-android-fragments.html&quot;&gt;advocating against it&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
In any case the community is steadily going in a direction where the good UI-architecture is common knowledge. Frameworks[2] are helping in that matter and blog posts like Dorfmann&#39;s and Artem Zin&#39;s &lt;a href=&quot;https://medium.com/@artem_zin/m-model-from-mvc-mvp-in-android-flow-and-mortar-bd1e50c45395&quot;&gt;post on the Model&lt;/a&gt;. Still, a term I seldom hear in the Android world is &lt;em&gt;View Model&lt;/em&gt; - but there really shouldn&#39;t be a reason for it. The View Model concept fits nicely into any MVC/MVP pattern. In this post I&#39;ll explain how you can and should split your model into two or even three layers of models.&lt;br /&gt;
&lt;p style=&quot;padding-left: 30px;font-size:80%&quot;&gt;[1] An example is the &lt;a href=&quot;http://developer.android.com/training/basics/network-ops/connecting.html&quot;&gt;Connecting to the Network&lt;/a&gt;-article. View, Model and presenter-code all in one file and the inner class DownloadWebpageTask have dependency to the Activity. Same mistake is done in &lt;a href=&quot;http://developer.android.com/training/basics/network-ops/xml.html&quot;&gt;Parsing XML Data&lt;/a&gt;. You could also question if they maybe should hint at 3rd-party libraries existing that greatly simplifies both XML-parsing and HTTP communication.&lt;/p&gt;&lt;p style=&quot;padding-left: 30px;font-size:80%&quot;&gt;[2] In addition to Framework-libraries, smaller libraries or micro-frameworks such as Dagger, Flow, Mortar, Parceler, Icepick and RxAndroid are building blocks which paved the way for MVP-frameworks.&lt;/p&gt;&lt;br /&gt;
&lt;h2 id=&quot;the-different-model-types&quot;&gt;The different model types&lt;/h2&gt;&lt;h3 id=&quot;the-view-model&quot;&gt;The View Model&lt;/h3&gt;In this post I&#39;m defining the View Model somewhat loosely as the model mirroring a concrete user interface. Martin Fowler names it the &lt;a href=&quot;http://martinfowler.com/eaaDev/PresentationModel.html&quot;&gt;Presentation Model&lt;/a&gt;. It differs from the Business Model in that it has filtered, merged or converted data for presentation in one specific context. From this follows that you can have multiple View Models for one Business Model, or multiple Business Models represented in one View Model. In the Microsoft MVVM pattern it is tightly coupled with the Business Model through &lt;em&gt;databinding&lt;/em&gt;. That is not a requirement in my definition and use, but it can certainly be implemented if that is a requirement in your project.&lt;br /&gt;
&lt;h3 id=&quot;the-business-model&quot;&gt;The Business Model&lt;/h3&gt;What I name the &quot;Business Model&quot; is the model representing an actual business entity. Think &lt;em&gt;user&lt;/em&gt;, &lt;em&gt;product&lt;/em&gt; , &lt;em&gt;supplier&lt;/em&gt; or &lt;em&gt;order&lt;/em&gt; in an online web shop system. In the Android code it contains strongly typed objects and business logic for working with these.&lt;br /&gt;
&lt;h3 id=&quot;the-transport-model&quot;&gt;The Transport Model&lt;/h3&gt;I&#39;m going to introduce a third model type I name &quot;The Transport Model&quot;. You will not always need it and even if you do you will not always have it as a separate class. The Transport Model is the model representing the business model &lt;em&gt;in transport&lt;/em&gt;. If you have a REST service, it will be the class representing the JSON-data. I&#39;ve found it useful to separate this as a standalone class as it allows me to unit test the parsing easily as well as allowing for switching the transport protocol with as little friction as possible. The pattern works very will with parser libraries such as Gson or Jackson.&lt;br /&gt;
&lt;h2 id=&quot;example&quot;&gt;Example&lt;/h2&gt;I&#39;m going to paint a scenario here with for a Movie Database app (heard it before?). The App fetches a list of movies with metadata from a JSON REST service and displays the list of movies in the app. Here is the JSON data:&lt;br /&gt;
&lt;pre class=&quot;brush:javascript&quot;&gt;{
    &quot;v&quot; : 1,
    &quot;data&quot; : [{
            &quot;released&quot; : &quot;2011-08-04&quot;,
            &quot;title&quot; : &quot;Hell on Wheels&quot;,
            &quot;category&quot; : &quot;TV series&quot;,
            &quot;id&quot; : &quot;tt1699748&quot;,
            &quot;stars&quot; : &quot;Anson Mount, Colm Meaney&quot;,
            &quot;image&quot; : [
                &quot;http://ia.media-imdb.com/images/M/MV5BMTQ5NTE5NTYzMF5BMl5BanBnXkFtZTgwOTc4OTY0MzE@._V1_.jpg&quot;,
                1297,
                1404
            ]
        },
        {
            &quot;released&quot; : &quot;2014-04-02&quot;,
            &quot;title&quot; : &quot;Hello Ladies: The Movie&quot;,
            &quot;category&quot; : &quot;TV movie&quot;,
            &quot;id&quot; : &quot;tt3762944&quot;,
            &quot;stars&quot; : &quot;Stephen Merchant, Christine Woods&quot;,
            &quot;image&quot; : [
                &quot;http://ia.media-imdb.com/images/M/MV5BMTQ5MjYxMjkwOV5BMl5BanBnXkFtZTgwODE3MjY0MzE@._V1_.jpg&quot;,
                1012,
                1500
            ]
        }
    ]
}
&lt;/pre&gt;So this with this JSON blob i want to illustrate a typical issue: The data itself is wrapped in a somewhat unnecessary object (with the version identifier). You don&#39;t want this and other unnecessary data to bleed into your app business model. Also you want the date, image and list of stars as strongly typed data objects - so you create a set of Transport Models separate from the Business Model:&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public class MovieJsonModel {
    public String released;
    public String title;
    public String category;
    public String id;
    public String stars;
    public ArrayList&amp;lt;Object&amp;gt; image;
}

public class MovieListJsonModel {
    String v; // Version
    public ArrayList&amp;lt;MovieJsonModel&amp;gt; data;
}
&lt;/pre&gt;The classes above can be directly parsed from the JSON feed using a one-liner with Gson:&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;MovieListJsonModel transportModel = new GsonBuilder().fromJson(jsonString, MovieListJsonModel.class);&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
The business model would look somewhat different:&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public class MovieModel {
    public String title;
    public String id;
    public Uri imageUri;
    public Date releaseDate;
    public ArrayList&amp;lt;String&amp;gt; stars;

    // Just illustrating that the model can and should contain business logic, 
    // not only data.
    public boolean isReleased() {
        return releaseDate != null &amp;amp;&amp;amp; releaseDate.before(new Date());
    }
}
&lt;/pre&gt;(To create a list of this simply instantiate an &lt;code&gt;ArrayList&amp;lt;MovieModel&amp;gt;&lt;/code&gt;.)&lt;br /&gt;
&lt;br /&gt;
So here you see that many of the String-fields in the Transport Model have gotten a strong typed counterpart. The Date, The image URI and the comma separated list of stars is actually an &lt;code&gt;ArrayList&lt;/code&gt;. I have not included the conversion code here but I&#39;d advice to put it in the Transport Model class. This way you will not introduce a dependency from the Business Model to the transport protocol.&lt;br /&gt;
&lt;br /&gt;
Finally an example of how a View Model could look:&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public class MovieViewModel {
    public String title;
    public String releaseDate;
    public Bitmap image;
    public int backgroundColor;
    public boolean isSelected;
}
&lt;/pre&gt;Here you can see that String-representation of the Date again. We want to control how a Java Date object is presented, and we do that when we create the View Model. Note that this also can be unit tested. Furthermore we have a Bitmap object for the image which earlier was represented with a URL. This of course requires us to actually load the image. I&#39;m not so determined on where to place this loading code - either in the View Model or in the Business Model.&lt;br /&gt;
&lt;br /&gt;
Finally there may be fields exclusively for the view, such as the &lt;code&gt;backgroundColor&lt;/code&gt; here, or state properties such as &lt;code&gt;isSelected&lt;/code&gt;. You may also have data from other Business Models, but I&#39;ve not included that in this example.&lt;br /&gt;
&lt;h2 id=&quot;persisting-the-state&quot;&gt;Persisting the state&lt;/h2&gt;One of the key benefits of having a specialized View Model is when you&#39;re persisting the model for state preservation. You probably know that you need to do this in case the system kills the process or if you rotate the device. The &lt;a href=&quot;https://github.com/johncarl81/parceler&quot;&gt;Parceler&lt;/a&gt; framework makes this simple, but we do need to make some adjustments to the simplified example above to accommodate for the non-parcelable Bitmap object:&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;@Parcel
public class MovieViewModel {
    public String title;
    public String releaseDate;
    @Transient public Bitmap image; 
    public int backgroundColor;
    public boolean isSelected;

    // Reference properties:
    public String imageUrl;  

    // A service client for downloading images asynchronously w/Rx
    private ImageService mImageService; 
}
&lt;/pre&gt;Now I&#39;ve included the image URL as a String as well (Uri is not parcelable either). The code to load the image could be like this, using RxAndroid for callbacks (could also be implemented as a standard callback):&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public Observable&amp;lt;Void&amp;gt; loadDataAsync() {
        if (image != null) return Observable.from(new Void[0]);
        else {
            Observable&amp;lt;Bitmap&amp;gt; imageObs = mImageService.loadImageAsync(movieModel.imageUri);
            Observable&amp;lt;Void&amp;gt; doneObs = imageObs
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .map(new Func1&amp;lt;Bitmap, Void&amp;gt;() {
                    @Override
                    public Void call(Bitmap bitmap) {
                        image = bitmap;
                        return null;
                    }
                });
            return doneObs;
        }
    }
&lt;/pre&gt;The View, Fragment or Activity would then ensure the data is always loaded as illustrated in the &lt;code&gt;onResume&lt;/code&gt; method here, while the &lt;code&gt;onCreate&lt;/code&gt; ensure the View Model object is always instantiated:&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public class MovieActivity
   private MovieViewModel mViewModel;

   @Override
   public void onCreate() {
       super.onCreate(Bundle savedInstanceState);
       if (savedInstanceState != null) {
           mViewModel = (MovieViewModel) savedInstanceState.getParcelable(&quot;ViewModel&quot;);
       }
   }

   @Override 
   public void onSaveInstanceState(Bundle outState) {
        outState.putParcelable(&quot;ViewModel&quot;, mViewModel);
        super.onSaveInstanceState(outState);
   }

   @Override
   public void onResume() {
       super.onResume();
        if (mViewModel != null) {
            loadAndBindViewModel();
        }
        else {
            // Load the models asynchronously from the REST Service, 
            // then call loadAndBindViewModel()
        }
    }

    private void loadAndBindViewModel() {    
       mViewModel.loadDataAsync().subscribe(new Action1&amp;lt;Void&amp;gt;() {
            @Override
            public void call(Void dummy) {
                modelToUi();
            }
        });
    }

    private void modelToUi() {
        // Map all View Model properties to actual view controls
    }
&lt;/pre&gt;There might be cases where you want to persist the Business Model as well (or instead), like if you&#39;re doing local caching of the service data. In this case you probably do not want to store it in the Bundle attached to the Activity or Fragment though, but instead use &lt;a href=&quot;http://developer.android.com/guide/topics/data/data-storage.html&quot;&gt;Shared Preferences, Internal Storage or SqLite&lt;/a&gt;. I will not go into details about that in this post.&lt;br /&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;The &quot;Model&quot; term in MVP/MVC covers all types of Model representations I&#39;ve touched upon here, but by sticking to the View Model representation you will separate the concerns of the transport, storage, business and presentation layer. Creating a separate View Model class will ensure you don&#39;t leak view-related stuff into the business layer, or transport-related fields into the business or view layer. Persisting the ViewModel class in the Bundle using Parceler will ensure that you retain the state of the view even after device rotations or process terminations.</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/3703313121211990685/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2015/04/dont-forget-view-model.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/3703313121211990685'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/3703313121211990685'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2015/04/dont-forget-view-model.html' title='Don&#39;t forget the View Model!'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-7956433944396368814</id><published>2014-06-08T03:07:00.002-07:00</published><updated>2015-04-19T02:43:39.543-07:00</updated><title type='text'>Building a solid JSON REST client in Android using Volley, Gson and Otto</title><content type='html'>Questions like &quot;How do you make an HTTP request on Android&quot; or &quot;How do you do async/background JSON requests on Android&quot;, are question that often arise on Stack Overflow and blogged about elsewhere. &lt;a href=&quot;http://stackoverflow.com/a/3028660/507339&quot;&gt;Often&lt;/a&gt; the &lt;a href=&quot;http://stackoverflow.com/a/3506039/507339&quot;&gt;answers&lt;/a&gt; contain somewhat low-level code who leave a lot undecided for the developer. Firing an AsyncTask for the request to allow the processing to happen off the UI thread is good, but what if the UI element who fired the request is destryed when the response arrives? And what about parsing the resulting JSON? What about caching and throttling? These are questions that will be addressed in this post. A complete working project will provided at the end.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;A word on Volley&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://android.googlesource.com/platform/frameworks/volley/&quot;&gt;Volley&lt;/a&gt; is a library by Google &lt;a href=&quot;https://www.youtube.com/watch?v=yhv8l9F44qo&quot;&gt;introduced at Google IO 2013&lt;/a&gt; which set out to make REST client implementation simpler and faster. Unfortunately Google hasn&#39;t seemed to embrace their own project to the max, as it still is undocumented and no references to it seems to be found on &lt;a href=&quot;http://developer.android.com&quot;&gt;developer.android.com&lt;/a&gt;. That doesn&#39;t stop it from being a powerful and effective library - enough &lt;a href=&quot;http://arnab.ch/blog/2013/08/asynchronous-http-requests-in-android-using-volley/&quot;&gt;blog&lt;/a&gt; &lt;a href=&quot;http://www.androidhive.info/2014/05/android-working-with-volley-library-1/&quot;&gt;posts&lt;/a&gt; exist about how to get started using it. This post goes a step further by introducing Gson for the simplest Json parsing. I also focus on 100% guarantee of any response being processed, which can be a challenge when dealing with &lt;a href=&quot;http://developer.android.com/guide/components/activities.html&quot;&gt;Android activity lifecycles&lt;/a&gt;. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;While most people would start out using AsyncTask for the request processing, Volley uses a thread pool of 4 threads by default. This has several advantages.   &lt;br /&gt;
&lt;ol&gt;&lt;li&gt;You don&#39;t need to spin up a thread each time a new request is sent. It&#39;s already there, waiting to serve you. Improves performance.&lt;br /&gt;
&lt;li&gt;A limit of 4 ensures you don&#39;t congest the Android operating system while still allowing you for a fair amount of parallellism&lt;br /&gt;
&lt;/ol&gt;If you do need more than 4 threads, you may download the Volley source code and tweak it yourself. If you need &lt;em&gt;a lot&lt;/em&gt; more than 4 threads, you probably have a use case more suited for libraries like &lt;a href=&quot;https://github.com/koush/ion&quot;&gt;Ion&lt;/a&gt;. You can still apply most of the techniques in this blog post to that framework though. &lt;/p&gt;&lt;p&gt;In addition to this, Volley provides optional caching of GET-requests, primarily intended for image caching. You might want to look into that depending on your needs. &lt;/p&gt;&lt;h2&gt;Gson instead of JsonObject&lt;/h2&gt;&lt;p&gt;On top of Volley I&#39;ll be using Gson and an extension to the &lt;span class=&quot;code&quot;&gt;Request&lt;/span&gt; class allowing for seamless Json-response-to-Pojo-mapping. If you don&#39;t know what Gson is, it&#39;s a framework by Google allowing for automatic parsing and mapping of Json strings to plain java objects. Example: &lt;/p&gt;&lt;p&gt;&lt;b&gt;Json:&lt;/b&gt;     &lt;pre class=&quot;brush:javascript&quot;&gt;{
        &quot;age&quot; : 14,
        &quot;name&quot;: &quot;ralph&quot;
    }
    &lt;/pre&gt;&lt;b&gt;Java class:&lt;/b&gt;     &lt;pre class=&quot;brush:java&quot;&gt;public class Person {
        public int age;
        public String name;
    }
    &lt;/pre&gt;This example uses fields, but you can use Java-bean properties if you prefer that (I don&#39;t). &lt;/p&gt;&lt;p&gt;The code to parse the Json to the object in this case would be a one-liner: &lt;pre class=&quot;brush:java&quot;&gt;String jsonString = &quot;{\&quot;age\&quot; : 14,\&quot;name\&quot;: \&quot;ralph\&quot;}&quot;;
    Person person = new Gson().fromJson(jsonString, Person.class); // assuming jsonString contains the json above
&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;Combining the power of Gson with Volley, we can make a GsonRequest-class which allows us to get a callback with the strongly typed object directly - never dealing with the intermediate parsing: &lt;pre class=&quot;brush:java&quot;&gt;public class GsonRequest&amp;lt;T&amp;gt; extends Request&amp;lt;T&amp;gt; {
    private final Gson gson = new Gson();
    private final Class&amp;lt;T&amp;gt; clazz;
    private final Map&amp;lt;String, String&amp;gt; headers;
    private final Listener&amp;lt;T&amp;gt; listener;
    
    public GsonRequest(String url, Class&amp;lt;T&amp;gt; classType, Map&amp;lt;String, String&amp;gt; headers,
                       Listener&amp;lt;T&amp;gt; listener, ErrorListener errorListener) {
        super(Method.GET, url, errorListener);
        this.clazz = classType;
        this.headers = headers;
        this.listener = listener;
    }
    
    public GsonRequest(String url, Class&amp;lt;T&amp;gt; classType,
                       Listener&amp;lt;T&amp;gt; listener, ErrorListener errorListener) {
        super(Method.GET, url, errorListener);
        headers = null;
        this.clazz = classType;
        this.listener = listener;
    }

    @Override
    public Map&amp;lt;String, String&amp;gt; getHeaders() throws AuthFailureError {
        return headers != null ? headers : super.getHeaders();
    }

    @Override
    protected void deliverResponse(T response) {
        listener.onResponse(response);
    }

    @Override
    protected Response&amp;lt;T&amp;gt; parseNetworkResponse(NetworkResponse response) {
        try {
            String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
            T parsedObject = gson.fromJson(json, clazz);
            return Response.success(parsedObject, HttpHeaderParser.parseCacheHeaders(response)); 
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JsonSyntaxException e) {
            return Response.error(new ParseError(e));
        }
    }
}
&lt;/pre&gt;&lt;h2&gt;Otto and the issue with device rotation and destroyed activities&lt;/h2&gt;&lt;p&gt;I&#39;m going to outline the following scenario of a poker game app for Android where a callback approach is uses for requests:     &lt;ol&gt;&lt;li&gt;User opens the activity where he&#39;ll be presented with the cards dealt to him&lt;br /&gt;
&lt;li&gt;The Activity fires the request to fetch the cards&lt;br /&gt;
&lt;li&gt;The user realizes this view is best presented in landscape mode and rotates the device&lt;br /&gt;
&lt;li&gt;Android kills the Activity which &quot;owns&quot; the request and creates a new one&lt;br /&gt;
&lt;li&gt;The request completes and calls back to the now dead activity. &lt;br /&gt;
&lt;li&gt;The dead activity is either smart enough to realize it&#39;s dead, so it discards the request, &lt;i&gt;or&lt;/i&gt; it tries to process it and the application crashes when tryin to updated a dead UI.&lt;br /&gt;
&lt;/ol&gt;This may sound as a far-fetched scenario or a rare edge case, but it is infact a real-life scenario I regularly encountered in production for a &lt;a href=&quot;http://www.chineseshowdown.com&quot;&gt;game I made&lt;/a&gt;. &lt;/p&gt;&lt;p&gt;The solution is based on introducing an Event Bus, also known as the &lt;a href=&quot;http://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern&quot;&gt;Pub/Sub-Pattern&lt;/a&gt;. I&#39;ve grown fond of &lt;a href=&quot;http://square.github.io/otto/&quot;&gt;the Otto library&lt;/a&gt; from Square Inc, which does a fine job at that.     Instead of having callbacks to the Activity, we rely on a dispatcher to publish the response on the event bus once any response arrives. Whether or not it is the original or a new instance of the Activity then listening, is irrelevant. &lt;/p&gt;&lt;figure&gt;         &lt;img src=&quot;http://data.nilzorblog.com/blogposts/android-volley-otto/rotate1.png&quot; width=&quot;180&quot;&gt;                 &lt;figcaption&gt;Illustration of timeline when the user rotates the device before the response arrives&lt;/figcaption&gt;     &lt;/figure&gt;      &lt;p&gt;Now a second challenge arise because there is a small gap between the time where the old activity is killed and the new is created. Context switches might occur here, responses may arrive and be lost. To amend for this I have in addition made a class called &lt;span class=&quot;code&quot;&gt;OttoGsonResponseBuffer&lt;/span&gt;, which will receive and buffer any requsts arriving in this gap. This way we ensure that no response is ever lost when the user rotates the device right after a request is sent.     &lt;figure&gt;         &lt;img src=&quot;http://data.nilzorblog.com/blogposts/android-volley-otto/rotate2.png&quot; width=&quot;280&quot;&gt;                   &lt;figcaption&gt;The response buffer handles responses arriving in the time gap where no activity lives&lt;/figcaption&gt;     &lt;/figure&gt; &lt;/p&gt;&lt;p&gt;The way this functions is that Otto supports producing of events through the &lt;span class=&quot;code&quot;&gt;@Produce&lt;/span&gt; attribute, which will cause the response data   to be resubmitted to the event bus once a new listener for that type of event subscribes.      &lt;/p&gt;&lt;p&gt;&lt;b&gt;A word of warning here&lt;/b&gt;: Be careful when you use this buffer with regards to memory use. There is no mechanism of timeout or automatic flushing of the buffer as it is implemented now. Do not activate the buffer when user presses the back button (or flush it after he does), only when rotating the device.     &lt;/p&gt;&lt;h2&gt;Source code&lt;/h2&gt;&lt;p&gt;A complete working example and a proof of concept can be found at my &lt;a href=&quot;https://github.com/Nilzor/OttoVolleyDoneRight&quot;&gt;OttoVolleyDoneRight&lt;/a&gt; github repo. It may also be used as a library by following the simple steps describe at the bottom of the README there.      &lt;/p&gt;&lt;p&gt;When launching the example you are presented with a simple button labeled &quot;HTTP Request&quot;, which will send off a request to &lt;a href=&quot;http://httpbin.org/delay/1&quot;&gt;http://httpbin.org/delay/1&lt;/A&gt;. This service always delays one second before responding, which allows you to test rotating the device while waiting. You can up the number 1 to whatever you like if 1 second is too short. Notice how the request is processed in the new activity instance after the device is done rotating and the response arrives.  &lt;/p&gt;&lt;h2&gt;Going further&lt;/h2&gt;The example provided here is a good start, but there are some properties you should be aware of which might not scale well or should be done different in your application, depending on your needs:   &lt;ol&gt;&lt;li&gt;There is just &lt;em&gt;one&lt;/em&gt; pair of HTTP resonse message-bus class defined: &lt;span class=&quot;code&quot;&gt;VolleyRequestSuccess/Failed&lt;/span&gt;. This means that you must check the type of response in the &lt;span class=&quot;code&quot;&gt;onHttpResponseReceived&lt;/span&gt;-methods of your listener classes. Due to &lt;a href=&quot;http://docs.oracle.com/javase/tutorial/java/generics/erasure.html&quot;&gt;type erasure&lt;/a&gt; in Java, you can only have one listener method in each class as it is now, and it will receive &lt;em&gt;any&lt;/em&gt; kind of response. &lt;br /&gt;
&lt;li&gt;The &lt;span class=&quot;code&quot;&gt;OttoGsonResponseBuffer&lt;/span&gt; doesn&#39;t autoflush. Potential memory leak. Be careful with where you place the&lt;br /&gt;
&lt;span class=&quot;code&quot;&gt;ResponseBuffer.startSaving()&lt;/span&gt;-method call.&lt;br /&gt;
&lt;/ol&gt;&lt;/p&gt;&lt;p&gt;In any case I believe this pattern provides a solid foundation for a JSON-based HTTP REST client for Android, and you&#39;ll have an application with fewer potential bugs than if you follow most other guides I&#39;ve read so far online. Feel free to argue against me or come with suggestions for improvements in the comment below.       &lt;/p&gt;&lt;!-- 
http://stackoverflow.com/questions/3505930/make-an-http-request-with-android/3506039#3506039

Promote at :

   -https://gist.github.com/JakeWharton/5616899
--&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/7956433944396368814/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2014/06/building-solid-json-rest-client-in.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/7956433944396368814'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/7956433944396368814'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2014/06/building-solid-json-rest-client-in.html' title='Building a solid JSON REST client in Android using Volley, Gson and Otto'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-7367889941058011673</id><published>2013-12-20T04:32:00.001-08:00</published><updated>2014-02-05T00:11:35.674-08:00</updated><title type='text'>A comparison of Javascript IDEs</title><content type='html'>&lt;style&gt;
 div.soj img {
  border: 1px gray solid;
 }
 div.soj .footnote {
  font-size: 85%;
  font-style: italic;
 }
 div.soj .sup {
  font-size: 50%;
  vertical-align: super;
 }
 div.soj figure {
  margin: 0.3em 0;
 }
 div.soj figcaption {
  font-size: 90%;
  font-style: italic; 
  margin: 0.3em 0;
 }
 div.soj h1 {
 }
 div.soj h2 {
 }
 div.soj h3 {
 }
 
 div.soj .results-link,div.soj .results-link:hover {
  float:right;
 }
 div.soj .results-link:hover {
  background: #F7F7F7;
 }
 
 div.soj table.result-matrix
 {
  margin-top: 7px;
  margin-bottom: 7px;
  border: solid 1px #d5e0ff;
 }
 div.soj table[class=result-matrix] td
 {
  font-family: Verdana, Helvetica, Sans-Serif;
  font-size: .8em;
  border: solid 1px #d5e0ff;
  color:Black;
  background: #F2F2F2;
  text-align:left;
 }
 div.soj table[class=result-matrix] th
 {
  font-family: Verdana, Helvetica, Sans-Serif;
  font-size: .8em;
  padding: 6px 5px;
  text-align: left;
  background-color: #e8eef4;
  border: solid 1px #d5e0ff;
 }
 
 div.soj table[class=result-matrix] th:nth-child(n+2) {
  text-align: center; 
 }
 div.soj table[class=result-matrix] td:nth-child(n+2) {
  text-align: center; 
  width: 70px;
  color:white;
  background: #333;
 }
 div.soj table[class=result-matrix] td.sub-feature {
  padding-left: 2em;    
 }
 
 div.soj td.partially {
  background:#770 !important;
 }
 
 td.yes {
  background:#070 !important;
 }
 
 div.soj td.no {
  background:#700 !important;
 }
@media (max-width : 1023px) {
   div.soj .m-large { display: none }
   div.soj td,div.soj th { padding: 2px; }
   div.soj table { border-collapse:collapse;}
}
@media (min-width : 1024px) {
   div.soj .m-small { display: none}
   div.soj td,div.soj th { padding: 4px; }

}
&lt;/style&gt;&lt;div class=&quot;soj&quot;&gt;&lt;a class=&quot;results-link&quot; href=&quot;#results&quot;&gt;Jump to results&lt;/a&gt;&lt;h2&gt;Motivation&lt;/h2&gt;&lt;p&gt;I am primarily a developer of .NET, but lately I&#39;ve been working more and more with Javascript and HTML5. Like many of my readers who&#39;ve also primarily been working with static languages like C# and Java, I also see the trend of applications previously only viable to develop in a compiled language, now being developed with web technology. The browser support of HTML5, Javascript and CSS3 is now very good across the board, so much that I&#39;m tempted to call it mature. When it comes to tooling though, I&#39;ve been surprised more than once to see professional developers &lt;a href=&quot;http://www.youtube.com/watch?v=8ILQOFAgaXE&quot;&gt;speaking&lt;/a&gt; &lt;a href=&quot;http://channel9.msdn.com/Events/WindowsAzure/AzureConf2012/B06&quot;&gt;at conferences&lt;/a&gt; bringing up their solution in what I presumed was simple text editors such as Sublime Text or Notepad++. Not that there&#39;s anything wrong with those editors, its just that they are just that: &lt;em&gt;Editors&lt;/em&gt;. Not IDEs: &lt;em&gt;Integrated Development Environments&lt;/em&gt; - products that have a birds eye perspective on your solution as a whole and aids you in crafting great &lt;em&gt;applications&lt;/em&gt; as apposed to &lt;em&gt;files&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;So was I wrong? There were three options:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Sublime Text has actually become a fully fledged IDE &lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Sublime Text is the state of the art of Javascript editors, although not on par with IDE&#39;s for static languages.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;The speakers aren&#39;t using the best tool available.&lt;br /&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;I decided to find out which of the three was true, and the result I present to you in this blog.&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;Scope&lt;/h2&gt;&lt;p&gt;What I&#39;ve done in this test is to gather a number of criteria I believe are essential in a modern IDE for effective programming. The criteria I bring with me from years of experience of using tools such as Visual Studio and Eclipse developing C# and Java. The criterias may not be exactly ties of the IDE/editor. The criteria I then tested on a range of IDE&#39;s which I believed were good developing Javascript, and   &lt;a href=&quot;http://stackoverflow.com/questions/925219/best-javascript-editor-or-ide-with-intellisense-and-debugging-possibly&quot;&gt;editors&lt;/a&gt;  &lt;a href=&quot;http://stackoverflow.com/questions/3919977/ide-for-node-js-javascript&quot;&gt;I&#39;ve seen others&lt;/a&gt; praise as good IDEs.&lt;br /&gt;
&lt;/p&gt;&lt;div class=&quot;footnote&quot;&gt;1) If you feel I&#39;ve left out some important criteria or editors, feel free to comment on this blog, and I&#39;ll consider compiling a version 2.&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;h2&gt;The criteria&lt;/h2&gt;Here is the list of criteria I tested:&lt;br /&gt;
&lt;h3&gt;1. Intellisense / auto-complete&lt;/h3&gt;Is the editor capable of providing typing hints both on framework and self-coded functions? Will it provide parameter info on all functions? Even on functions in other files? This is an important feature both because it helps on typing speed, but more importantly it reminds you what the signature of any function is. It will save you a lot of Googling (framework functions) and solution&lt;span class=&quot;sup&quot;&gt;2&lt;/span&gt; navigation (own functions). This is a &lt;em&gt;major&lt;/em&gt; time-saver when properly implemented.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;footnote&quot;&gt;2) I use the term &lt;em&gt;solution&lt;/em&gt; as meaning a set of HTML, Javascript, CSS and content files which have some sort of interdependency, and together form an application.&lt;/div&gt;&lt;figure&gt;&lt;br /&gt;
&lt;img src=&quot;http://data.nilzorblog.com/javascript-ides/ex-1-netbeans.png&quot;&gt;&lt;figcaption&gt;Intellisense on a framework function in Netbeans&lt;/figcaption&gt;&lt;/figure&gt;&lt;br /&gt;
&lt;h3&gt;2. Solution navigation&lt;/h3&gt;&lt;p&gt;&lt;i&gt;Go to definition:&lt;/i&gt; When the signature of the function is not enough and you want to view (or edit) the contents of the function, a quick way to navigate to the function call you&#39;re looking at is useful. This should be a one-keystroke shortcut from anywhere in the solution. This also goes for variables, as it for instance can be useful to see the initialization code of the variable. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;&lt;i&gt;Find usages:&lt;/i&gt; (Aka &quot;Find references&quot;) Could be used to navigate to a concrete usage which you don&#39;t remember exactly where was, or it could be used to determine what the impact of a change of this function will have. Not in terms of renaming the function, because refactoring should take care of that, but for changing behavior.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;&lt;i&gt;Navigate to file:&lt;/i&gt; When the cursor is on the &quot;href&quot; or &quot;src&quot; part of a script- or stylesheet-tag, you should be able to navigate to that file with a single key press.&lt;br /&gt;
&lt;/p&gt;&lt;h3&gt;3. Refactor: Rename&lt;/h3&gt;&lt;p&gt;Of all the refactoring functions, this is the one I use most often. This is the only one I&#39;m truly dependent on. I utilize and appreciate others, but if the IDE doesn&#39;t have support for solution-wide renaming, you&#39;re in trouble. Most likely you&#39;ll often end up with sticking with original names of all functions and variables as the program evolves, because of the hassle of changing names. But behavior and meaning of functions change. So should names. There&#39;s nothing I hate more than finding a code base with the function &lt;em&gt;getDollarValue&lt;/em&gt; only to find it accepts a parameter for an arbitrary currency.  &lt;br /&gt;
&lt;/p&gt;&lt;h3&gt;4. Code outline view&lt;/h3&gt;I find it useful to have a quick overview of a file or class in a window pane next to the code itself. It quickly gives you an indication of the size of the file, it&#39;s role and concerns. It helps you keep the architecture clean and the code tight, in addition to be a navigational aid. &lt;br /&gt;
&lt;figure&gt;&lt;br /&gt;
&lt;img src=&quot;http://data.nilzorblog.com/javascript-ides/ex-5-netbeans.png&quot;&gt;&lt;br /&gt;
&lt;figcaption&gt;The Navigator pane in Netbeans&lt;/figcaption&gt;&lt;/figure&gt; &lt;br /&gt;
&lt;h3&gt;5. Syntax error highlighting&lt;/h3&gt;In a parsed language this is even more important than in a compiled one. Why should I have to waste time running the application and checking the console view only to find out I forgot a semicolon? &lt;br /&gt;
&lt;figure&gt;&lt;br /&gt;
&lt;img src=&quot;http://data.nilzorblog.com/javascript-ides/ex-6-vs.png&quot;&gt;&lt;figcaption&gt;Syntax error hint in Visual Studio 2013&lt;/figcaption&gt;&lt;br /&gt;
&lt;/figure&gt;&lt;h3&gt;Debugging (not included)&lt;/h3&gt;Some of the IDEs have debugging capabilities. I haven&#39;t considered this feature essential because all the majors browsers have this now so you might as well use the browser for debugging. For those who have it though (All but Sublime), it &lt;em&gt;might&lt;/em&gt; be better to use the IDE-debugger for convenience.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;The editors&lt;/h2&gt;&lt;h3&gt;Visual Studio 2013&lt;/h3&gt;&lt;figure&gt; &lt;br /&gt;
&lt;a href=&quot;http://data.nilzorblog.com/javascript-ides/ide-vs.png&quot;&gt;&lt;img class=&quot;ide&quot; src=&quot;http://data.nilzorblog.com/javascript-ides/ide-vs.png&quot; style=&quot;width: 300px;&quot;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/figure&gt;  &lt;br /&gt;
&lt;a href=&quot;http://www.visualstudio.com/&quot;&gt;Visual Studio&lt;/a&gt; from Microsoft should be well known from anyone coming from a C++ or .NET-world. It&#39;s a monster of an IDE both in terms of size and list of features. In the later years Microsoft have had great focus on improving the support for Web technology, including Javascript. They&#39;re not quite there yet but they&#39;re getting there. &lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Visual Studio 2013 + #Resharper&lt;/h3&gt;If you purchase &lt;a href=&quot;http://www.jetbrains.com/resharper/&quot;&gt;Jetbrains&#39; Resharper&lt;/a&gt;-plugin for Visual Studio, you&#39;re getting all the coding support you need and more. It&#39;s going to cost you though - not only the license cost of Resharper (~$150 for a personal license), but you&#39;re not getting away with the Express edition of Visual Studio anymore either. &lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;WebStorm&lt;/h3&gt;&lt;figure&gt; &lt;br /&gt;
&lt;a href=&quot;http://data.nilzorblog.com/javascript-ides/ide-webstorm.png&quot;&gt;&lt;img class=&quot;ide&quot; src=&quot;http://data.nilzorblog.com/javascript-ides/ide-webstorm.png&quot; style=&quot;width: 300px;&quot;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/figure&gt;  &lt;br /&gt;
Jetbrains is not only developing VS-plugins. They have their own IDE(s). &lt;a href=&quot;http://www.jetbrains.com/webstorm/&quot;&gt;WebStorm&lt;/a&gt;&#39;s Javascript support is nothing short of superb. The sister-product &lt;a href=&quot;http://www.jetbrains.com/phpstorm/&quot;&gt;PhpStorm&lt;/a&gt; also adds support for the PHP language, if you&#39;re into that.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Eclipse&lt;/h3&gt;&lt;figure&gt; &lt;br /&gt;
&lt;a href=&quot;http://data.nilzorblog.com/javascript-ides/ide-eclipse.png&quot;&gt;&lt;img class=&quot;ide&quot; src=&quot;http://data.nilzorblog.com/javascript-ides/ide-eclipse.png&quot; style=&quot;width: 300px;&quot;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/figure&gt;  &lt;br /&gt;
One can&#39;t write a review of an IDE of &lt;em&gt;any&lt;/em&gt; language without mentioning Eclipse. I was actually quite impressed with the Javascript features you get for &lt;em&gt;free&lt;/em&gt; (as in beer) from this IDE. It doesn&#39;t come for free in regards of man-hours though. First you need to install the &lt;a href=&quot;http://www.eclipse.org/webtools/jsdt/&quot;&gt;Javascript Developer Tools plug-in&lt;/a&gt;, then you have to configure the key bindings for the functions you&#39;ll need, and &lt;em&gt;then&lt;/em&gt; - if you&#39;re lucky - you may start being productive (&lt;a href=&quot;http://stackoverflow.com/questions/20563065/javascript-support-in-eclispe-why-doesnt-content-assist-suggest-dom-methods&quot;&gt;I wasn&#39;t that lucky&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Sublime Text 3 + SublimeCodeIntel (ST3+SCI)&lt;/h3&gt;&lt;figure&gt; &lt;br /&gt;
&lt;a href=&quot;http://data.nilzorblog.com/javascript-ides/ide-st3.png&quot;&gt;&lt;img class=&quot;ide&quot; src=&quot;http://data.nilzorblog.com/javascript-ides/ide-st3.png&quot; style=&quot;width: 300px;&quot;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/figure&gt;  &lt;br /&gt;
&lt;a href=&quot;http://www.sublimetext.com/&quot;&gt;Sublime Text 3&lt;/a&gt; (ST3) is a very sleek and good looking editor with a lot of nifty features you don&#39;t find anywhere else. But is it an IDE? Everywhere when the discussion of Javascript editing in ST3 comes up, the add-in &lt;a href=&quot;https://github.com/SublimeCodeIntel/SublimeCodeIntel&quot;&gt;SublimeCodeIntel&lt;/a&gt; is mentioned in the next sentence. This package will give you Javascript intellisense and some navigational functions and blurs the line between an editor and an IDE.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Cloud9&lt;/h3&gt;&lt;figure&gt;&lt;br /&gt;
&lt;a href=&quot;http://data.nilzorblog.com/javascript-ides/ide-c9.png&quot;&gt;&lt;img class=&quot;ide&quot; src=&quot;http://data.nilzorblog.com/javascript-ides/ide-c9.png&quot; style=&quot;width: 300px;&quot;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/figure&gt;&lt;br /&gt;
&lt;a href=&quot;https://c9.io&quot;&gt;Cloud9&lt;/a&gt; is stands out in the crowd as the only web-based IDE. I saw it mentioned in &lt;a href=&quot;http://stackoverflow.com/questions/3919977/ide-for-node-js-javascript&quot;&gt;a closed question&lt;/a&gt; on Stack Overflow addressing the same question as I do in this blog post. I must admit I was highly skeptical to a web-based IDE and didn&#39;t have very high expectations going in. But I was surprised and impressed how far they have come. They have It still doesn&#39;t quite make it to elite league of IDEs, but I&#39;ll be following the development of this and similar services keenly in the years to come. &lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Google Chrome&lt;/h3&gt;&lt;figure&gt; &lt;br /&gt;
&lt;a href=&quot;http://data.nilzorblog.com/javascript-ides/ide-chrome.png&quot;&gt;&lt;img class=&quot;ide&quot; src=&quot;http://data.nilzorblog.com/javascript-ides/ide-chrome.png&quot; style=&quot;width: 300px;&quot;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/figure&gt;  &lt;br /&gt;
&lt;p&gt;Wait a second, you say.. Isn&#39;t that a &lt;em&gt;browser?&lt;/em&gt; You&#39;re including both text editors and &lt;em&gt;browsers&lt;/em&gt; in this test? Yes I do. Because people are &lt;a href=&quot;http://gregrickaby.com/turn-chrome-developer-tools-into-an-ide/&quot;&gt;starting to claim&lt;/a&gt; that &lt;a href=&quot;http://www.reddit.com/r/webdev/comments/1t1nun/chrome_canarys_webkit_inspector_just_turned_into/&quot;&gt;Chrome is an IDE.&lt;/a&gt; I wanted to test if that claim held up. From my results you&#39;ll see that it didn&#39;t. It&#39;s a &lt;em&gt;great&lt;/em&gt; Javascript debugger and on-the-fly hack-tool, but it&#39;s not an IDE. Yet.&lt;br /&gt;
&lt;br /&gt;
&lt;/p&gt;&lt;h3&gt;vim (not included)&lt;/h3&gt;&lt;p&gt;Vim is not included in this test. Many developers use Vim sort of as an IDE (comparable to Sublime Text 3) and would probably like me to include it. I didn&#39;t do that primarily because I don&#39;t have the time to get to know Vim and its plugins well enough to be able to answer all the questions. From what I&#39;ve read, you should be able to get some &lt;a href=&quot;http://stackoverflow.com/a/5893447/507339&quot;&gt;Code hints (intellisense)&lt;/a&gt; and also a &lt;a href=&quot;http://stackoverflow.com/a/5893600/507339&quot;&gt;Tag list&lt;/a&gt; which acts like a Code outline view. Refactoring support is absent as far as I can tell.&lt;/p&gt;&lt;p&gt;I don&#39;t believe anyone should switch to Vim solely because they&#39;re looking for a good Javascript IDE. There might be many good reasons to learn Vim, but as far as Javascript IDE&#39;s goes, it&#39;s not the best as of today. I know it&#39;s an editor - not an IDE, but  the same goes for Sublime Text 3. Yet these lines seem to blur.&lt;br /&gt;
&lt;a id=&quot;results&quot;&gt;&amp;nbsp;&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;The result matrix&lt;/h2&gt;&lt;p&gt;So here are the results, after hours of installing, configuring and testing code in the different IDE&#39;s:&lt;/p&gt;&lt;table class=&quot;result-matrix&quot; name=&quot;result-matrix&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;th&gt;Feature\IDE&lt;/th&gt;&lt;th&gt;&lt;span class=&quot;m-large&quot;&gt;VS2013&lt;/span&gt;&lt;span class=&quot;m-small&quot;&gt;VS&lt;/span&gt;&lt;/th&gt;&lt;th&gt;&lt;span class=&quot;m-large&quot;&gt;VS2013+R#&lt;/span&gt;&lt;span class=&quot;m-small&quot;&gt;VS+ R#&lt;/span&gt;&lt;/th&gt;&lt;th&gt;&lt;span class=&quot;m-large&quot;&gt;WebStorm&lt;/span&gt;&lt;span class=&quot;m-small&quot;&gt;WS&lt;/span&gt;&lt;/th&gt;&lt;th&gt;&lt;span class=&quot;m-large&quot;&gt;Netbeans&lt;/span&gt;&lt;span class=&quot;m-small&quot;&gt;Nb&lt;/span&gt;&lt;/th&gt;&lt;th&gt;&lt;span class=&quot;m-large&quot;&gt;Eclipse&lt;/span&gt;&lt;span class=&quot;m-small&quot;&gt;Ec&lt;/span&gt;&lt;/th&gt;&lt;th&gt;&lt;span class=&quot;m-large&quot;&gt;ST3+SCI&lt;/span&gt;&lt;span class=&quot;m-small&quot;&gt;ST3&lt;/span&gt;&lt;/th&gt;&lt;th&gt;&lt;span class=&quot;m-large&quot;&gt;Cloud9&lt;/span&gt;&lt;span class=&quot;m-small&quot;&gt;C9&lt;/span&gt;&lt;/th&gt;&lt;th&gt;&lt;span class=&quot;m-large&quot;&gt;Chrome&lt;/span&gt;&lt;span class=&quot;m-small&quot;&gt;Ch&lt;/span&gt;&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;9&quot;&gt;1. Intellisense&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;sub-feature&quot;&gt;a) DOM functions    &lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;sub-feature&quot;&gt;b) Own functions/variables  &lt;/td&gt;&lt;td class=&quot;partially&quot;&gt;*&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;partially&quot;&gt;*&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;partially&quot;&gt;*&lt;/td&gt;&lt;td class=&quot;partially&quot;&gt;*&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;sub-feature&quot;&gt;c) ...showing parameter list   &lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;partially&quot;&gt;*&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;sub-feature&quot;&gt;d) File references (src, href) &lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;9&quot;&gt;2. Navigation&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;sub-feature&quot;&gt;a) Go to declaration   &lt;/td&gt;&lt;td class=&quot;partially&quot;&gt;*&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;partially&quot;&gt;*&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;partially&quot;&gt;*&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;sub-feature&quot;&gt;b) Navigate to file (src, href) &lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;partially&quot;&gt;*&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;sub-feature&quot;&gt;c) Find usages     &lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;9&quot;&gt;3. Refactor: Rename &lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;sub-feature&quot;&gt;a) Functions     &lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;partially&quot;&gt;*&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;span class=&quot;sup&quot;&gt;1&lt;/span&gt;&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;sub-feature&quot;&gt;b) Variables     &lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;partially&quot;&gt;*&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;span class=&quot;sup&quot;&gt;2&lt;/span&gt;&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;4. Outline*view          &lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;5. Syntax error highlighting      &lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;/td&gt;&lt;td class=&quot;yes&quot;&gt;Y&lt;/td&gt;&lt;td class=&quot;no&quot;&gt;N&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;footnote&quot;&gt;*) Only within the scope of a single file. Not solution-wide.&lt;/div&gt;&lt;div class=&quot;footnote&quot;&gt;1) I&lt;a href=&quot;http://stackoverflow.com/questions/20563065/javascript-support-in-eclispe-why-doesnt-content-assist-suggest-dom-methods&quot;&gt;couldn&#39;t get this to work&lt;/a&gt;, but it&#39;s &lt;a href=&quot;http://www.eclipse.org/pdt/help/html/using_javascript_content_assist.htm&quot;&gt;supposed to work&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;footnote&quot;&gt;2) Only when using the &quot;var&quot;-keyword in front. When in form &quot;mylib.someVar&quot;, it does not work.&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;
Please leave a comment if you find any errors in the table.&lt;br /&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;p&gt;I was pleasantly surprised on how good the Javascript support were in many of the IDEs I hadn&#39;t tested previously. I was similarly disappointed with Visual Studio 2013 out of the box, which I thought had better support after hearing talks from Microsoft-guys the later years on the focus on web technology for their IDE. Sublime Text 3 performed as expected - it&#39;s good for quick editing of small projects, but it won&#39;t hold up for larger project against the other guys.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;I won&#39;t name a single IDE as &lt;em&gt;the best&lt;/em&gt; - I haven&#39;t tested them all well enough for that. But if you are developing large Javascript applications, you won&#39;t go wrong with either VS2013 with Resharper, Netbeans, WebStorm or Eclipse. I guess it depends more on what you&#39;re used to, what your project manager offers or what your wallet can afford.&lt;/p&gt;&lt;p&gt;As for the question coined in the &quot;motivation&quot; section - I&#39;d say it&#39;s a clear #3, given the question was &quot;best tool for developing Javascript solutions&quot;. I do understand that in a presentation context, other factors may come to play. In short: choose whatever tool you like, but please make a consious and educated decision! I hope this article have contributed in educating you just a little bit.&lt;br /&gt;
&lt;/p&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/7367889941058011673/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2013/12/a-comparison-of-javascript-ides.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/7367889941058011673'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/7367889941058011673'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2013/12/a-comparison-of-javascript-ides.html' title='A comparison of Javascript IDEs'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-5126491253287181455</id><published>2013-12-19T03:45:00.000-08:00</published><updated>2013-12-19T03:48:57.358-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="conversion"/><category scheme="http://www.blogger.com/atom/ns#" term="git"/><category scheme="http://www.blogger.com/atom/ns#" term="hg"/><category scheme="http://www.blogger.com/atom/ns#" term="mercurial"/><category scheme="http://www.blogger.com/atom/ns#" term="visual-studio-online"/><title type='text'>Pushing from Mercurial to an empty, non-bare Git repo on Windows</title><content type='html'>&lt;p&gt;Today there&#39;s good, 2-way  integration between Git and Mercurial. Git has &lt;a href=&quot;http://hg-git.github.io/&quot;&gt;hg-git&lt;/a&gt; which is an extension that allows you to clone, push and pull git repos. Likewise Git has &lt;a href=&quot;http://felipec.wordpress.com/2012/11/13/git-remote-hg-bzr-2/&quot;&gt;git-remote-hg&lt;/a&gt; for interacting with Mercurial-repos. Both of these extension come pre-compiled with the git and hg-installations I&#39;m using on Windows, so getting them to work was simply a matter of configuration.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;What wasn&#39;t that simple though, was getting the first push through. I had an empty repo at &lt;a href=&quot;http://www.visualstudio.com&quot;&gt;Visual Studio Online&lt;/a&gt; which I wanted to populate with the check-in history of my Mercurial repo. I met obstacles because non-bare Git repo&#39;s doesn&#39;t appreciate being pushed to by Mercurial. See this article on &lt;a href=&quot;http://www.bitflop.com/document/111&quot;&gt;bare vs non-bare repos&lt;/a&gt; for more info. So then I tried pulling from git instead, but that was equally challenging because I needed Python-support in Git for the git-remote-hg extension to work. Apparently &lt;a href=&quot;http://stackoverflow.com/questions/15438165/access-mercurial-repo-with-git-on-windows&quot;&gt;that is not supported in Windows&lt;/a&gt;. &lt;br /&gt;
&lt;/p&gt;&lt;p&gt;&lt;b&gt;Solution: Create an intermediary &lt;i&gt;bare&lt;/i&gt; git-repo.&lt;/b&gt;&lt;br /&gt;
&lt;p&gt;So, here&#39;s the receipe of command you need to execute in order to complete the conversion. I&#39;m not including the CD-commands - the foledr you need to be in is indicated on each line. Assumptions:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;&lt;em&gt;HgSource&lt;/em&gt; is the source repository with a history&lt;br /&gt;
&lt;li&gt;&lt;em&gt;GitTarget&lt;/em&gt; is the empty, non-bare git-repo you want to push to&lt;br /&gt;
&lt;li&gt;&lt;em&gt;c:\GitTempTarget&lt;/em&gt; is simply an empty Windows folder &lt;br /&gt;
&lt;/ol&gt;&lt;/p&gt;&lt;p&gt;&lt;pre style=&quot;font-family:monospace;color:black;font-size:120%&quot;&gt;c:\GitTarget&gt; git config --local receive.denyCurrentBranch warn
 c:\GitTempTarget&gt; git --bare init
 c:\HgSource&gt; hg push c:\GitTempTarget
 c:\HgGitTempTarget&gt; git push c:\GitTarget master
 c:\HgGitTarget&gt; git config --local --unset receive.denyCurrentBranch
&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;Note: This is a one-time conversion of the repository. I have tried pushing consecutive changesets from HgSource directly to HgGitTarget without success. If anyone know how to achieve that, please drop a comment below.&lt;br /&gt;
&lt;br /&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/5126491253287181455/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2013/12/pushing-from-mercurial-to-empty-non.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/5126491253287181455'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/5126491253287181455'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2013/12/pushing-from-mercurial-to-empty-non.html' title='Pushing from Mercurial to an empty, non-bare Git repo on Windows'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-4787288895509322378</id><published>2013-12-07T03:42:00.001-08:00</published><updated>2013-12-07T04:06:47.619-08:00</updated><title type='text'>Configuring an &quot;I feel lucky&quot; search shortcut in Chrome</title><content type='html'>I normally blog about programming stuff, but this is just one of those &quot;superuser life pro tips&quot; that I feel I have to preach to the world. You know those times when you need refreshed how to do &lt;a href=&quot;https://www.google.com/search?q=Padding+With+String+Format&amp;btnI=Im+Feeling+Lucky&quot;&gt;Padding with String Format&lt;/a&gt; and you just &lt;i&gt;know&lt;/i&gt; you&#39;re gonna click the top result? Or the argument list of &lt;a href=&quot;https://www.google.com/search?q=php+strstr&amp;btnI=Im+Feeling+Lucky&quot;&gt;PHP strstr&lt;/a&gt;,  that stinking &lt;a href=&quot;https://www.google.com/search?q=java+parse+string+to+datetime&amp;btnI=Im+Feeling+Lucky&quot;&gt;DateTime parsing&lt;/A&gt; in Java? Or, or or... &lt;br /&gt;
&lt;br /&gt;
The &quot;I feel lucky&quot;-function has been around for years, but it&#39;s really not effective. You have to 1. Go to www.google.com, 2. type the search text, 3. move the mouse over to the &quot;I feel lucky&quot; link and click. No one goes to google.com anymore anyways, right? You just type in the search address bar, or &quot;omnibox&quot; as it&#39;s called in Chrome. But you&#39;re still forced to do two moves because you have to see the results first. That of course is &lt;a href=&quot;http://www.businessinsider.com/google-just-effectively-killed-the-im-feeling-lucky-button-2010-9&quot;&gt;not by accident&lt;/a&gt;. But we&#39;re programmers. We work around stuff :-)&lt;br /&gt;
&lt;br /&gt;
Hence I present you the Google I-Feel-Luck &quot;search engine&quot;. It&#39;s not rocket science, but I had to Google it to get the answer (Thank you &lt;a href=&quot;http://productforums.google.com/d/msg/chrome/F-fdSjNh3K8/4JUXn2rfrxwJ&quot;&gt;timmmy_42&lt;/a&gt;). This is how to do it in Chrome (but I guess there&#39;s equivalents in both IE, Firefox and Opera):&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Open Settings &lt;img src=&quot;http://data.nilzorblog.com/blogposts/lucky/settings.png&quot;&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;Click on Manage Search Engines &lt;br /&gt;
&lt;img src=&quot;http://data.nilzorblog.com/blogposts/lucky/manage-search-engines.png&quot;&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;Create a new entry with the following parameters:&lt;br /&gt;
&lt;/ol&gt;&lt;table style=&quot;padding-left:30px&quot;&gt;&lt;tr&gt;&lt;td style=&quot;font-weight:bold&quot;&gt;Search engine:&lt;td&gt;&quot;Google Lucky&quot; (or other name of your choice)&lt;br /&gt;
&lt;tr&gt;&lt;td style=&quot;font-weight:bold&quot;&gt;Keyword&lt;td&gt;&quot;l&quot; (or other short keyword of your choice)&lt;br /&gt;
&lt;tr&gt;&lt;td style=&quot;font-weight:bold&quot;&gt;URL&lt;td&gt;https://www.google.com/search?q=%s&amp;btnI&lt;br /&gt;
&lt;/table&gt;&lt;br /&gt;
&lt;br /&gt;
Voila! You may now perform an &quot;I feel lucky&quot; search in chrome by prefixing your search with the letter L in the omnibox. Example:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;img src=&quot;http://data.nilzorblog.com/blogposts/lucky/result-1.png&quot;&gt;&lt;br /&gt;
&lt;br /&gt;
Click enter:&lt;br /&gt;
&lt;br /&gt;
&lt;img src=&quot;http://data.nilzorblog.com/blogposts/lucky/result-2.png&quot;&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;edit:&lt;/b&gt; I&#39;ve noticed that Google doesn&#39;t always bring you directly to the result even if you do include the Im-feeling-lucky query parameter (the Java example in my post for instance). If anyone can find a pattern in when this happens, I&#39;d be glad to learn more about this.&lt;br /&gt;
&lt;br /&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/4787288895509322378/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2013/12/configuring-i-feel-lucky-search.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/4787288895509322378'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/4787288895509322378'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2013/12/configuring-i-feel-lucky-search.html' title='Configuring an &quot;I feel lucky&quot; search shortcut in Chrome'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-5379317447105380706</id><published>2013-05-19T13:01:00.003-07:00</published><updated>2013-10-17T06:31:27.485-07:00</updated><title type='text'>101 LINQ Samples Lambda style</title><content type='html'>I have many times had use for the &lt;a href=&quot;http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b&quot;&gt;101 LINQ samples&lt;/a&gt; by Microsoft when needing to refresh how to do different kind of queries in with &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/vstudio/bb397926.aspx&quot;&gt;Linq&lt;/a&gt;. Often I prefer to have them expressed in Lambda or &quot;fluent&quot; syntax instead of query syntax though, so it has always bothered me that they haven&#39;t published them in both formats. Luckily there are tools that allow you to automate conversion between the two formats. I used &lt;a href=&quot;http://www.jetbrains.com/resharper/&quot;&gt;Resharper by Jetbrains&lt;/a&gt; to perform the conversion semi-automatically and have now published all 101*) examples for you in lambda/fluent syntax.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: 0.7em;&quot;&gt;*) Actually there are 102, but hey :) &lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Head over to&amp;nbsp;&lt;a href=&quot;http://linq101.nilzorblog.com/linq101-lambda.php&quot;&gt;linq101.nilzorblog.com&lt;/a&gt;&amp;nbsp;to see the result.&lt;br /&gt;
&lt;br /&gt;
Download source (VS2010 project): &lt;a href=&quot;http://linq101.nilzorblog.com/linq101-lambda-source.zip&quot;&gt;linq101-lambda-source.zip&lt;/a&gt; &lt;br /&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/5379317447105380706/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2013/05/101-linq-samples-lambda-style.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/5379317447105380706'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/5379317447105380706'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2013/05/101-linq-samples-lambda-style.html' title='101 LINQ Samples Lambda style'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-7005301068976113791</id><published>2013-02-11T03:01:00.000-08:00</published><updated>2013-02-11T04:25:56.496-08:00</updated><title type='text'>A HelloWorld-example of a Jersey REST service hosted at Google AppEngine</title><content type='html'>In this short tutorial I will outline the project setup and deployment steps needed to get a Jersey REST-application up and running at Google AppEngine. There are a couple of non-intuitive issues that got me struggling for days - hopefully you won&#39;t have to do the same.&lt;br /&gt;
&lt;h2&gt;1. Environment and AppEngine installation&lt;/H2&gt;&lt;p&gt;&lt;p&gt;I will be using the following IDE, framework and SDK versions in this example. Installation of these are out of the scope of this post but I will provide a couple of links:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://www.oracle.com/technetwork/java/javase/downloads/index.html&quot;&gt;Java Development Kit (JDK) 1.6 SE &lt;/a&gt;&lt;div class=&quot;footnote&quot;&gt;JDK 1.7 is not fully supported by AppEngine&lt;/div&gt;&lt;li&gt;&lt;a href=&quot;https://developers.google.com/appengine/docs/java/gettingstarted/installing&quot;&gt;AppEngine SDK&lt;/a&gt;  v1.7.4&lt;br /&gt;
&lt;li&gt;&lt;a href=&quot;http://www.eclipse.org/downloads/packages/eclipse-ide-java-ee-developers/junosr1&quot;&gt;Eclipse Juno EE&lt;/a&gt;&lt;br /&gt;
&lt;/ul&gt;&lt;/p&gt;&lt;p&gt;After installing the AppEngine SDK and the &lt;a href=&quot;https://developers.google.com/appengine/docs/java/tools/eclipse&quot;&gt;plugin for Eclipse&lt;/a&gt; you shall have the Google Toolbar available as well. Use this as a verification that you&#39;re done with the installation phase.  &lt;/p&gt;&lt;p&gt;&lt;img border=1 src=&quot;http://data.nilzorblog.com/blogposts/rest-at-gae/gae-plugin.png&quot;&gt;  &lt;/p&gt;&lt;h2&gt;2. Project setup&lt;/h2&gt;Go to &lt;span class=&quot;code&quot;&gt;File &gt; New &gt; Other...&lt;/span&gt; (or Ctrl+N) and select &lt;span class=&quot;code&quot;&gt;Google &gt; Web Application Project&lt;/span&gt;  &lt;p&gt;&lt;a href=&quot;http://data.nilzorblog.com/blogposts/rest-at-gae/new-project.png&quot;&gt;&lt;img src=&quot;http://data.nilzorblog.com/blogposts/rest-at-gae/new-project.png&quot; width=300&gt;&lt;/a&gt; &lt;p&gt;Give your project a name and a namespace and unselect &quot;Use Google Web Toolkit&quot;, as we won&#39;t have any UI in our application. Also uncheck &quot;Generate project sample code&quot;. &lt;p&gt;&lt;a href=&quot;http://data.nilzorblog.com/blogposts/rest-at-gae/new-project-wizard.png&quot;&gt;&lt;img src=&quot;http://data.nilzorblog.com/blogposts/rest-at-gae/new-project-wizard.png&quot; width=300&gt;&lt;/a&gt; &lt;p&gt;Now go to Project Properties (Alt+Enter while focusing on the project root in the Project Explorer) and go to &lt;span class=&quot;code&quot;&gt;Google &gt; App Engine&lt;/span&gt;. Select &lt;span class=&quot;code&quot;&gt;v1&lt;/span&gt; of Datanucleus JDO/JPA version. This is because using v2 will generate a dependency conflict on the file version of asm*.jar which Jersey also depends on. &lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://data.nilzorblog.com/blogposts/rest-at-gae/datanucleus-v1.png&quot;&gt;&lt;img src=&quot;http://data.nilzorblog.com/blogposts/rest-at-gae/datanucleus-v1.png&quot; width=300&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Now copy all of the following jar files from the Jersey home page into your &lt;span class=&quot;code&quot;&gt;/war/WEB-INF/lib&lt;/span&gt; folder: &lt;table class=&quot;grid-1&quot;&gt;&lt;tr&gt;&lt;th&gt;JAR file&lt;th&gt;Role&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;jersey-bundle-1.17.jar&lt;td rowspan=&quot;2&quot; valign=top&gt;&lt;a href=&quot;http://jersey.java.net/nonav/documentation/latest/user-guide.html#core_server&quot;&gt;Core Jersey Server components&lt;/a&gt;&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;jettison-1.1.jar&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;activation-1.1.1.jar&lt;td rowspan=&quot;7&quot; valign=top&gt;&lt;a href=&quot;http://jersey.java.net/nonav/documentation/latest/user-guide.html#d4e1718&quot;&gt;POJO-to-JSON object mapping support&lt;/a&gt;&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;jackson-core-asl-1.9.2.jar&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;jackson-jaxrs-1.9.2.jar&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;jackson-mapper-asl-1.9.2.jar&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;jaxb-api-2.2.4.jar&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;jaxb-impl-2.2.4-1.jar&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;stax-api-1.0-2.jar&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;http://repository.codehaus.org/org/codehaus/jackson/jackson-xc/1.9.11/jackson-xc-1.9.11.jar&quot;&gt;jackson-xc-1.9.11.jar&lt;/a&gt;&lt;td&gt;Allows you to use JAXB annotations and &lt;a href=&quot;http://stackoverflow.com/questions/10860142/appengine-java-jersey-jackson-jaxbannotationintrospector-noclassdeffounderror&quot;&gt;rids of an initial exception&lt;/a&gt; if you don&#39;t&lt;br /&gt;
&lt;/table&gt;&lt;p&gt;Note that the links from the Jersey.java.net-page always links to the newest version of Jersey. I can only guarantee that this tutorial works with the exact specified versions of the jar&#39;s. &lt;br /&gt;
&lt;p&gt;Remove &lt;span class=&quot;code&quot;&gt;asm-4.0.jar&lt;/span&gt; from the lib-folder. Note that you have asm-3.3.1.jar there instead.&lt;br /&gt;
&lt;p&gt;Finally right click on jersey-bundle-1.17.jar and select &lt;span class=&quot;code&quot;&gt;Build Path &gt; Add to build path&lt;/span&gt;&lt;br /&gt;
&lt;h2&gt;3. Implementing a Hello world method&lt;/h2&gt;&lt;p&gt;Add a new class &lt;span class=&quot;code&quot;&gt;HelloWorldObject&lt;/span&gt; to the namespace &quot;com.example&quot; or whatever namespace you chose for your project. Let the conent of that class be the following:&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public class HelloWorldObject {
 public String text = &quot;Hello world&quot;;
}
&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;Add a new class &lt;span class=&quot;code&quot;&gt;HelloWorldApi&lt;/span&gt; to the same namespace. Let it contain this:&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;

 @Path(&quot;/hello&quot;)
 public class HelloWorldApi {
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public HelloWorldObject getHelloWorld() {
   return new HelloWorldObject();
  }
 }
&lt;/pre&gt;&lt;p&gt;Edit the file /war/WEB-INF/web.xml. Add a new servlet definition &quot;HelloWorldServlet&quot;:&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; (...)&amp;gt;  
 &amp;lt;servlet&amp;gt;
  &amp;lt;description&amp;gt;Hello World Service&amp;lt;/description&amp;gt;
  &amp;lt;servlet-name&amp;gt;HelloWorldServlet&amp;lt;/servlet-name&amp;gt;
  &amp;lt;servlet-class&amp;gt;com.sun.jersey.spi.container.servlet.ServletContainer&amp;lt;/servlet-class&amp;gt;
  &amp;lt;init-param&amp;gt;
   &amp;lt;param-name&amp;gt;com.sun.jersey.config.property.packages&amp;lt;/param-name&amp;gt;
   &amp;lt;param-value&amp;gt;nilsnett.chinese.backend&amp;lt;/param-value&amp;gt;
  &amp;lt;/init-param&amp;gt;
  &amp;lt;init-param&amp;gt;
   &amp;lt;param-name&amp;gt;com.sun.jersey.api.json.POJOMappingFeature&amp;lt;/param-name&amp;gt;
   &amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt;
  &amp;lt;/init-param&amp;gt;
  &amp;lt;init-param&amp;gt;
   &amp;lt;param-name&amp;gt;com.sun.jersey.config.feature.DisableWADL&amp;lt;/param-name&amp;gt;
   &amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt;
  &amp;lt;/init-param&amp;gt;
  &amp;lt;load-on-startup&amp;gt;1&amp;lt;/load-on-startup&amp;gt;
 &amp;lt;/servlet&amp;gt;
 &amp;lt;servlet-mapping&amp;gt;
  &amp;lt;servlet-name&amp;gt;HelloWorldServlet&amp;lt;/servlet-name&amp;gt;
  &amp;lt;url-pattern&amp;gt;/api/*&amp;lt;/url-pattern&amp;gt;
 &amp;lt;/servlet-mapping&amp;gt;

 &amp;lt;servlet&amp;gt;
  &amp;lt;servlet-name&amp;gt;SystemServiceServlet&amp;lt;/servlet-name&amp;gt;
  &amp;lt;servlet-class&amp;gt;com.google.api.server.spi.SystemServiceServlet&amp;lt;/servlet-class&amp;gt;
  &amp;lt;init-param&amp;gt;
   &amp;lt;param-name&amp;gt;services&amp;lt;/param-name&amp;gt;
   &amp;lt;param-value /&amp;gt;
  &amp;lt;/init-param&amp;gt;
 &amp;lt;/servlet&amp;gt;
 &amp;lt;servlet-mapping&amp;gt;
  &amp;lt;servlet-name&amp;gt;SystemServiceServlet&amp;lt;/servlet-name&amp;gt;
  &amp;lt;url-pattern&amp;gt;/_ah/spi/*&amp;lt;/url-pattern&amp;gt;
 &amp;lt;/servlet-mapping&amp;gt;
&amp;lt;/web-app&amp;gt;
&lt;/pre&gt;A couple of notes:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;The POJOMappingFeature-param is the one enabling support for returning standard Java objects directly from an API method which then gets serialized to JSON behind the scenes using Jackson. See the &lt;a href=&quot;http://wiki.fasterxml.com/JacksonDocumentation&quot;&gt;Jackson documentation&lt;/a&gt; on how to tweak the output generated here.&lt;br /&gt;
&lt;li&gt;The DisableWADL-parameter disables use of reflection, which is banned at Google App Engine. &lt;br /&gt;
&lt;li&gt;I&#39;m leaving the SystemServiceServlet as it is. You might not need this though.&lt;br /&gt;
&lt;/ol&gt;&lt;h2&gt;4. Deployment&lt;/h2&gt;The deployment part couldn&#39;t be easier. Right click on the project root in the Project Explorer, click &lt;span class=&quot;code&quot;&gt;Google &amp;gt; Deploy to App Engine&lt;/span&gt;. If you haven&#39;t already, you&#39;ll be guided into the App Engine project settings in order to set your Application ID. When that is done and if everything goes well, you should have the service available in about 30 seconds. &lt;h2&gt;5. Testing and further reading&lt;/h2&gt;&lt;p&gt;Finally it&#39;s time to test the service. The url will be &lt;span class=&quot;code&quot;&gt;http://yourAppEngineDomain.appspot.com/api/hello&lt;/span&gt;. The output should be like this in Chrome: &lt;p&gt;&lt;img src=&quot;http://data.nilzorblog.com/blogposts/rest-at-gae/test-jersey.png&quot;&gt;  &lt;p&gt;From this point on, the fun part starts. If you&#39;re new to Jersey I a good starting point is to read . A good starting point is the &lt;a href=&quot;http://www.vogella.com/articles/REST/article.html&quot;&gt;REST with Java (JAX-RS) using Jersey Tutorial&lt;/a&gt; by Lars Vogel. That post contains a lot of setup information that is irrelevant for Google AppEngine though, but &lt;a href=&quot;http://www.vogella.com/articles/REST/article.html#restjersey_annotations&quot;&gt;chapter 2.2 JAX-RS annotations&lt;/A&gt;, and the example in &lt;a href=&quot;http://www.vogella.com/articles/REST/article.html#crud_class&quot;&gt;chapter 7.3 Rest Service&lt;/a&gt; are still very relevant.&lt;br /&gt;
&lt;br /&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/7005301068976113791/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2013/02/a-helloworld-example-of-jersey-rest.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/7005301068976113791'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/7005301068976113791'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2013/02/a-helloworld-example-of-jersey-rest.html' title='A HelloWorld-example of a Jersey REST service hosted at Google AppEngine'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-7129496331553585969</id><published>2013-02-09T08:20:00.000-08:00</published><updated>2013-02-11T01:21:50.002-08:00</updated><title type='text'>Jersey vs Google Cloud Endpoints as REST-service at Google AppEngine</title><content type='html'>&lt;style&gt;.li-smaller{font-size:100%;margin-bottom:8px;}.footnote {font-size:80%;font-style:italic}img {margin:6px}.syntaxhighlighter{width: auto !important}&lt;/style&gt;&lt;p&gt;Last week I wrote about &lt;a href=&quot;http://www.nilzorblog.com/2013/02/a-google-cloud-endpoints-hello-world.html&quot;&gt;how to use Google Cloud Endpoints&lt;/a&gt; (or &quot;Endpoints&quot; for short) to create a JSON-producing REST-service at Google App Engine. This week I will present an alternate approach, using the &lt;a href=&quot;http://jersey.java.net/&quot;&gt;Jersey REST framework&lt;/a&gt; with &lt;a href=&quot;http://en.wikipedia.org/wiki/JSON&quot;&gt;JSON&lt;/a&gt; &lt;a href=&quot;http://en.wikipedia.org/wiki/Plain_Old_Java_Object&quot;&gt;POJO&lt;/A&gt; support. In this post I will discuss the rationale as to why, while in the next post I will describe how.&lt;/p&gt;&lt;p&gt;So why do we need another approach? Why not use Google&#39;s own REST implementation instead of pushing extra jar&#39;s to AppEngine bloating the solution? Well the implementations are different of course and I can think of several reasons to choose Jersey over Google Clound Endpoints:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Google Endpoints is still in beta&lt;br /&gt;
&lt;div class=&quot;li-smaller&quot;&gt;&lt;a href=&quot;http://endpoints-trusted-tester.appspot.com&quot;&gt;Google themselves&lt;/a&gt; don&#39;t recommend you using Endpoints in production systems yet. This should be reason enough. The poor documentation and error messages in the framework are others.&lt;/div&gt;&lt;li style=&quot;text-decoration: line-through&quot;&gt;Better flexibility&lt;br /&gt;
&lt;div class=&quot;li-smaller&quot;&gt;The Endpoints framework enforces a strict RESTful architecture. Although you may view this as a good thing, most real-world &quot;REST services&quot; today diverge to some extent from the true RESTful principles as outlined by the Godfather of REST himself, Roy Fielding in &lt;a href=&quot;http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven&quot;&gt;this blog post&lt;/A&gt;. A simpler, pragmatic approach to REST is &lt;a href=&quot;http://www.intridea.com/blog/2010/4/29/rest-isnt-what-you-think-it-is&quot;&gt;not necessarily a bad thing&lt;/a&gt; though.&lt;/div&gt;&lt;li&gt;Better portability&lt;br /&gt;
&lt;div class=&quot;li-smaller&quot;&gt;By using a third-party API for endpoint-generation you will have a smoother ride if you at any point need to migrate to a different platform than Google AppEngine.&lt;/div&gt;&lt;/ol&gt;&lt;p&gt;The kicker for me was the flexibility. The true &lt;a href=&quot;http://en.wikipedia.org/wiki/Restful&quot;&gt;RESTful architecture&lt;/a&gt; leaves no room for business logic on the server. All operations must be dumb CRUD-operations. While this results in a highly scalable architecture, it&#39;s not one fitted for all back-end scenarios. If you want to create a RPC-service based on JSON over HTTP* (is there a name for this?), you need a framework that allows you to define the input and output types arbitrarily and map them to the HTTP verbs as you wish. &lt;span style=&quot;text-decoration: line-through&quot;&gt;Google Endpoints does not that&lt;/span&gt;. In short, these two restrictions are the one causing trouble (or consitency, depending on your point of view=:&lt;/p&gt;
&lt;p style=&quot;padding-left:40px; font-style:italic&quot;&gt;&lt;b&gt;Update 11th feb 2013:&lt;/b&gt; See last paragraph with an update that refutes this &quot;kicker&quot;.&lt;/p&gt;&lt;/p&gt;&lt;div class=&quot;footnote&quot;&gt;*If you do this, be careful not to call it a &quot;REST Service&quot;, as Roy Fielding will &lt;a href=&quot;http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven&quot;&gt;hunt you down&lt;/a&gt; for public scalding.&lt;/div&gt;&lt;ol&gt;&lt;li&gt;The URI will be named after the class name of the return type&lt;br /&gt;
&lt;li&gt;If you have a complex object as input (POJO), the output must be of same type&lt;br /&gt;
&lt;/ol&gt;&lt;p&gt;What if you want to create an advanced search routine which takes a filter object as input and returns the list of entities as output? In Jersey you can do that the following way: &lt;p&gt;&lt;pre class=&quot;brush:java&quot;&gt;@Path(&quot;/api-base/user&quot;)
 public class User {
  @POST
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  public ArrayList&lt;user&gt; searchUsers(UserFilter filter) {    
   ArrayList&lt;user&gt; users = new ArrayList&lt;user&gt;();
   // Populate users through search logic
   return users;
  }
 }
 
 public class UserFilter {
  public String text;
  public String zipCode;
  public String maxAge;
 }
&lt;/pre&gt;&lt;p&gt;You would then use this search function by doing an HTTP POST to &lt;span class=&quot;code&quot;&gt;http://host/api-base/user&lt;/span&gt; where the POST payload is a JSON representation of the UserFilter object, e.g. &lt;span class=&quot;code&quot;&gt;{ &quot;text&quot; : &quot;roger&quot; }&lt;/span&gt;&lt;/p&gt;&lt;p&gt;If we try to do the same with Endpoints we need to adhere to rule #2 mentioned above, and thus we&#39;ll be unable to take a UserFilter object as input while returning ArrayList&amp;lt;user&amp;gt;. We could get around it by creating a parameter for each of the optional filter parameters, but this would force the consumer to always pass something for these values as the Endpoints framework would produce a 404-error otherwise: &lt;p&gt;&lt;pre class=&quot;brush:java&quot;&gt;@Api(name = &quot;api-base&quot;)
 public class Api {
  public ArrayList&lt;user&gt; getUsers(@Named String text, @Named String zipCode, @Named String maxAge) {    
   ArrayList&lt;user&gt; users = new ArrayList&lt;user&gt;();
   // Populate users through search logic
   return users;
  }
 }
&lt;/pre&gt;&lt;p&gt;To use this you would then to a HTTP GET to &lt;span class=&quot;code&quot;&gt;http://host/api-base/user/TEXT/ZIP/MAXAGE&lt;/span&gt; where the uppercase-text in that URL are the parameter values. This is not very flexible as you need to pass all parameters always.&lt;/p&gt;&lt;h3&gt;Summary&lt;/h3&gt;I&#39;m aware this is a superficial and subjective comparison of the two frameworks. There are a lot of other factors that I haven&#39;t considered, like performance and security. I do believe I&#39;ve highlighted the main differences from a developer&#39;s and architect&#39;s point of view though - and if nothing else I hope to get feedback and counter-arguments to my points. &lt;p&gt;Finally I&#39;d like to underline that the Google Cloud Endpoints framework still is in Beta, and that all my arguments in this post may be void tomorrow. This is the state of the framework as of today though, and I hope my post can help people make the right decision when it comes to framework for REST-ish services at AppEngine.
&lt;hr&gt;&lt;p&gt;&lt;b&gt;Update 11th feb 2013:&lt;/b&gt;.&lt;/p&gt;&lt;p&gt;I had not read the documentation well enough. There is indeed full flexibility when it comes to URL generation and input-output-class types with Google Endpoints - Good news! Thanks to Dan Holevoet from Google pointing this out in the comments.&lt;p&gt;Implementing the search example above using Google Endpoints is done like this:
&lt;p&gt;&lt;pre class=&quot;brush:java&quot;&gt;@Api(name = &quot;api-base&quot;)
 public class Api {
  @ApiMethod(httpMethod = &quot;POST&quot;, path = &quot;searchUsers&quot;)
  public ArrayList&lt;user&gt; getUsers(UserFilter filter) {    
   ArrayList&lt;user&gt; users = new ArrayList&lt;user&gt;();
   // Populate users through search logic
   return users;
  }
 }
&lt;/pre&gt;&lt;p&gt;&lt;b&gt;Or&lt;/b&gt; you could implement it with optional GET-parameters this way:
&lt;p&gt;&lt;pre class=&quot;brush:java&quot;&gt;@Api(name = &quot;api-base&quot;)
 public class Api {
  @ApiMethod(httpMethod = &quot;GET&quot;, path = &quot;searchUsers&quot;)
  public ArrayList&lt;user&gt; getUsers(@Named(&quot;text&quot;) String text, @Named(&quot;zipCode&quot;) String zipCode, @Named(&quot;maxAge&quot;) String maxAge) {    
   ArrayList&lt;user&gt; users = new ArrayList&lt;user&gt;();
   // Populate users through search logic
   return users;
  }
 }
&lt;/pre&gt;&lt;/p&gt;
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/7129496331553585969/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2013/02/jersey-vs-google-cloud-endpoints-as.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/7129496331553585969'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/7129496331553585969'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2013/02/jersey-vs-google-cloud-endpoints-as.html' title='Jersey vs Google Cloud Endpoints as REST-service at Google AppEngine'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-1277574751298538912</id><published>2013-02-05T12:00:00.000-08:00</published><updated>2013-02-11T01:11:29.221-08:00</updated><title type='text'>A Google Cloud Endpoints Hello-World example in Java using Eclipse</title><content type='html'>&lt;!--&lt;script src=&quot;http://data.nilzorblog.com/scripts/FancyZoom.js&quot;&gt;&lt;/script&gt;&lt;script src=&quot;http://data.nilzorblog.com/scripts/FancyZoomHTML.js&quot;&gt;&lt;/script&gt;--&gt;&lt;style&gt;.footnote {font-size:80%;font-style:italic}img {margin:6px}.syntaxhighlighter{width: auto !important}&lt;/style&gt;&lt;br /&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;For the last couple of days I&#39;ve been working to get a simple REST service up and running at Google AppEngine using the &lt;a href=&quot;http://endpoints-trusted-tester.appspot.com/&quot;&gt;Google Cloud Endpoints&lt;/a&gt; framework presented at Google IO 2012. The introduction at the page just linked to in addition to the &lt;a href=&quot;https://docs.google.com/document/d/1sloZ36iSmq16piwaZxaq1ssMsUE0Z-jdL721ky7sVKM/edit#&quot;&gt;documentation&lt;/a&gt; gave the impression that this was a very simple and straight forward framework to use. It might be, but I still used three days to get a hello world application up and running. The reason for this is compound. I may be an idiot, but I will also put part of the blame on an incomplete documentation by Google. The Google Cloud Endpoints techonology (&quot;Endpoints&quot; from now) is still only in semi-closed beta though, so I should probably not expect more. In any case, I am writing this blog post so that others will only use the single hour needed to get a hello world app up and running instead of the full three days* I used.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;&lt;div class=&quot;footnote&quot;&gt;*) Some of this time was spent testing other PaaS REST technologies as well as waiting for answers on forum posts, but still...&lt;br /&gt;
&lt;/div&gt;&lt;/p&gt;&lt;h2&gt;Access, installation and environment&lt;/H2&gt;&lt;p&gt;The Endpoints technology is available for all to use - you do not need to join the &lt;a href=&quot;https://groups.google.com/forum/?fromgroups#!forum/endpoints-trusted-testers&quot;&gt;trusted testers group&lt;/a&gt; other than for getting access to the documentation. You should still of course do this. I will also refer to this documentation in this post. I&#39;m just saying that the framework is indeed embedded in the AppEngine SDK v1.7 which I am using. &lt;/p&gt;&lt;p&gt;I will be using the following IDE, framework and SDK versions in this example. Installation of these are out of the scope of this post but I will provide a couple of links:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://www.oracle.com/technetwork/java/javase/downloads/index.html&quot;&gt;Java Development Kit (JDK) 1.6 SE &lt;/a&gt;&lt;div class=&quot;footnote&quot;&gt;JDK 1.7 is not fully supported by AppEngine&lt;/div&gt;&lt;li&gt;&lt;a href=&quot;https://developers.google.com/appengine/docs/java/gettingstarted/installing&quot;&gt;AppEngine SDK&lt;/a&gt;  v1.7.4&lt;br /&gt;
&lt;li&gt;&lt;a href=&quot;http://www.eclipse.org/downloads/packages/eclipse-ide-java-ee-developers/junosr1&quot;&gt;Eclipse Juno EE&lt;/a&gt;&lt;br /&gt;
&lt;/ul&gt;&lt;/p&gt;&lt;p&gt;After installing the AppEngine SDK and the &lt;a href=&quot;https://developers.google.com/appengine/docs/java/tools/eclipse&quot;&gt;plugin for Eclipse&lt;/a&gt; you shall have the Google Toolbar available as well. Use this as a verification that you&#39;re done with the installation phase.  &lt;/p&gt;&lt;p&gt;&lt;img border=1 src=&quot;http://data.nilzorblog.com/blogposts/rest-at-gae/gae-plugin.png&quot;&gt;  &lt;/p&gt;&lt;h2&gt;Creating the project&lt;/h2&gt;&lt;p style=&quot;float:right&quot;&gt;&lt;a href=&quot;http://data.nilzorblog.com/blogposts/rest-at-gae/new-project.png&quot;&gt;&lt;img src=&quot;http://data.nilzorblog.com/blogposts/rest-at-gae/new-project.png&quot; width=&quot;200&quot;&gt;&lt;/a&gt;   &lt;a href=&quot;http://data.nilzorblog.com/blogposts/rest-at-gae/new-project-wizard.png&quot;&gt;&lt;img  src=&quot;http://data.nilzorblog.com/blogposts/rest-at-gae/new-project-wizard.png&quot; width=&quot;200&quot;&gt;&lt;/a&gt;  &lt;a href=&quot;http://data.nilzorblog.com/blogposts/rest-at-gae/eclipse-project.png&quot; &gt;&lt;img src=&quot;http://data.nilzorblog.com/blogposts/rest-at-gae/eclipse-project.png&quot; width=&quot;200&quot;&gt;&lt;/a&gt;  &lt;/p&gt;&lt;ol&gt;&lt;li&gt;Go to &lt;span class=&quot;code&quot;&gt;File &amp;gt; New other&lt;/span&gt; or hit Ctrl+N in Eclipse. Select Google &amp;gt; Web Application Project.&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;Enter a project name, a package name and uncheck the use of Google Web Toolkit which is a GUI framework we won&#39;t be needing for a back-end solution. I will be using &quot;com.example&quot; as package name in this example. Whenever I refer to this package name later, replace with your.&lt;br /&gt;
&lt;li&gt;Delete &lt;span class=&quot;code&quot;&gt;/src/com.example/HelloWorldServlet.java&lt;/span&gt; and &lt;span class=&quot;code&quot;&gt;/war/index.html&lt;/span&gt; as we will not be using these.&lt;br /&gt;
&lt;li&gt;Create a new class /src/com.example/HelloWorldEndpoint.java. Let the content be the following:&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;package com.example;

    import com.google.api.server.spi.config.Api;

    @Api(name = &quot;example&quot;)
    public class HelloWorldEndpoint {
     public Container getThing() {
      Container c = new Container();
      c.Text = &quot;Hello world!&quot;;
      return c;
     }
     
     public class Container {
      public String Text;
     }
    }
   &lt;/pre&gt;&lt;li&gt;Edit /war/WEB-INF/web.xml and set the init-param &lt;span class=&quot;code&quot;&gt;SystemServiceServlet&lt;/span&gt; to point to HelloWorldEndpoint instead of HelloWorldServlet. You can delete the HelloWorld-servlet definition entierly, leaving the final web.xml to look like this (namespaces in web-app tag removed for brevity):&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; standalone=&quot;no&quot;?&gt;
    &lt;web-app xmlns=&quot;(...)&quot;&gt;
     &lt;servlet&gt;
      &lt;servlet-name&gt;SystemServiceServlet&lt;/servlet-name&gt;
      &lt;servlet-class&gt;com.google.api.server.spi.SystemServiceServlet&lt;/servlet-class&gt;
      &lt;init-param&gt;
       &lt;param-name&gt;services&lt;/param-name&gt;&lt;param-value&gt;com.example.HelloWorldEndpoint&lt;/param-value&gt;&lt;/init-param&gt;
     &lt;/servlet&gt;
     &lt;servlet-mapping&gt;
      &lt;servlet-name&gt;SystemServiceServlet&lt;/servlet-name&gt;
      &lt;url-pattern&gt;/_ah/spi/*&lt;/url-pattern&gt;
     &lt;/servlet-mapping&gt;
    &lt;/web-app&gt;
&lt;/pre&gt;&lt;/ol&gt;&lt;h2&gt;Testing&lt;/h2&gt;Launch your app by selecting &lt;span class=&quot;code&quot;&gt;Run &gt; Run&lt;/span&gt; while for instance HelloWorldEndpoint.Java file is open. Jetty Application Server will launch and the Console in Eclipse will display a bunch of output. One of the final lines should be this, which indicates you&#39;re good to go: &lt;p&gt;&lt;span style=&quot;padding-lefT:20px&quot; class=&quot;Code&quot;&gt;INFO: The admin console is running at http://localhost:8888/_ah/admin&lt;/span&gt; &lt;/p&gt;&lt;p&gt;Your port may vary from 8888. Use this info to launch a web browser at the following URL, replacing 8888 with whatever port your server is running at: &lt;/p&gt;&lt;span style=&quot;padding-lefT:20px&quot; class=&quot;Code&quot;&gt;http://localhost:8888/_ah/api/example/v1/container&lt;/span&gt; &lt;/p&gt;&lt;p&gt;The result should be the following:&lt;/p&gt;&lt;img style=&quot;padding-lefT:20px&quot; src=&quot;http://data.nilzorblog.com/blogposts/rest-at-gae/browser-result.png&quot;&gt; &lt;p&gt;&lt;h2&gt;How URL&#39;s are generated&lt;/h2&gt;&lt;i&gt;&lt;p style=&quot;padding-left:40px&quot;&gt;&lt;b&gt;UPDATE 11th Feb 2013:&lt;/b&gt; The following section was written without knowledge of the &lt;span class=&quot;code&quot;&gt;path&lt;/span&gt; and &lt;span 
class=&quot;code&quot;&gt;httpMethod&lt;/span&gt;-parameters of the &lt;span class=&quot;code&quot;&gt;@ApiMethod&lt;/span&gt; annotation. See &lt;a href=&quot;https://docs.google.com/document/d/1sloZ36iSmq16piwaZxaq1ssMsUE0Z-jdL721ky7sVKM/edit#&quot;&gt;the documentation&lt;/a&gt;. While the below is still true, it&#39;s far less important to know how URL&#39;s are generated because you&#39;re not bound to it.&lt;/i&gt;
&lt;/p&gt;&lt;p&gt;Now this is the part that got me. The official &lt;a href=&quot;https://docs.google.com/document/d/1PDjYt-Ff2HnXmXSWTf7-pBxuAQd5z9NNeXC-0Wb2VDM/edit&quot;&gt;Google Cloud Endpoint documentation for Java&lt;/a&gt; (as per February 5th 2013) does not specify in detail how the URL&#39;s are generated. Instead it encourages you to go ahead and create the client libraries and consume the service that way. While that is the end goal for me as well, I like to know the intermediate steps so that I can debug better and possibly open up for creating clients not supported by the client-code-generating library, like Windows Phone. &lt;/p&gt;&lt;p&gt;The URL&#39;s to access your services in a HTTP REST-manner*** is generated in a combination of class/method annotation and code convention. This is the general rule from the point of view of a URL: &lt;/p&gt;&lt;p&gt;&lt;span class=&quot;code&quot;&gt;http://host:port/ServiceRoot/ApiName/Version/Entity/param1/param2/paramN&lt;/span&gt; &lt;/p&gt;&lt;table class=&quot;grid-1&quot;&gt;&lt;th&gt;Keyword&lt;th&gt;Maps to&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;ServiceRoot&lt;td&gt;As configured in &lt;span class=&quot;code&quot;&gt;&amp;lt;url-pattern&amp;gt;&lt;/span&gt; of the servlet mapping in web.xml&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;ApiName&lt;td&gt;The name-parameter of the @Api annotation of the class mapped in &lt;span class=&quot;code&quot;&gt;services&lt;/span&gt; class in web.xml (&lt;i&gt;API-class&lt;/i&gt; from now). &lt;br /&gt;
&lt;tr&gt;&lt;td&gt;Version&lt;td&gt;The version parameter of the @Api annotation of the class mapped in &lt;span class=&quot;code&quot;&gt;services&lt;/span&gt; class in web.xml. (Default: &quot;v1&quot;)&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;Entity&lt;td&gt;The class name in lowercase which an API method returns - &lt;b&gt;except&lt;/b&gt; for remove-methods, where it&#39;s taken from the postfix of the method name (sigh...)&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;Param1/2/N&lt;td&gt;(Optional) Value of the N&#39;th @Named annotation of any method parameter of type String or int&lt;br /&gt;
&lt;/table&gt;&lt;br /&gt;
&lt;p&gt;&lt;div class=&quot;footnote&quot;&gt;***) The framework also generates endpoints accessible through some HTTP RPC URL-convention, which I don&#39;t know how works. Feedback on this appreciated.&lt;/div&gt;&lt;/p&gt;&lt;p&gt;In addition to this, the prefix of any method name in the API-class will determine to which HTTP request method it will respond. The full table of these prefixes, from my knowledge is:&lt;br /&gt;
&lt;/p&gt;&lt;table class=&quot;grid-1&quot;&gt;&lt;tr&gt;&lt;th&gt;Prefix&lt;th&gt;HTTP method&lt;th&gt;Return constraint&lt;th&gt;Input constraint&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;get&lt;td&gt;GET&lt;td&gt;Any class T&lt;td&gt;None or any number of @Named parameter of type String/int&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;list&lt;td&gt;GET&lt;td&gt;T[] or List&amp;lt;T&amp;gt;&lt;td&gt;None or any number of @Named parameter of type String/int&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;insert&lt;td&gt;POST&lt;td&gt;Any class T1&lt;td&gt;One class T2**** and any number of @Named parameter of type String/int&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;update&lt;td&gt;PUT&lt;td&gt;Any class T1&lt;td&gt;One class T2 and any number of @Named parameter of type String/int&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;remove&lt;td&gt;DELETE&lt;td&gt;Any class T&lt;td&gt;None or any number of @Named parameter of type String/int&lt;br /&gt;
&lt;/table&gt;&lt;p class=&quot;footnote&quot;&gt;****) Should, but need not, be equal to type T1&lt;/p&gt;&lt;p&gt;In all of the examples, &lt;i&gt;class T&lt;/i&gt; is typically any business entity class. It cannot be System.String.&lt;br /&gt;
&lt;/p&gt;Just to summarize and underline some of the facts I&#39;ve deduced from these rules and from experimenting:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;The framework relies heavily on reflection and code convention to find out which methods to expose and how&lt;br /&gt;
&lt;li&gt;You do not need to annotate any methods, although the &lt;span class=&quot;code&quot;&gt;@ApiMethod&lt;/span&gt; can be used for convenience (see client library generation)&lt;br /&gt;
&lt;li&gt;All parameters must be annotaded with &lt;span class=&quot;code&quot;&gt;@Named&lt;/span&gt;.&lt;br /&gt;
&lt;li&gt;If you break any of these rules the framework will give you a 404 error without any further explanation. &lt;br /&gt;
&lt;/ol&gt;&lt;/p&gt;&lt;h3&gt;A couple of examples:&lt;/h3&gt;&lt;p&gt;1. From the hellow world-example with one get-method, this is how the framework maps it to a URL: &lt;p&gt;&lt;b&gt;CODE&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;http://data.nilzorblog.com/blogposts/rest-at-gae/url-example-2.png&quot;&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;URL&lt;/b&gt; &lt;p&gt;&lt;span class=&quot;code&quot;&gt;HTTP &lt;span style=&quot;color:blue&quot;&gt;GET&lt;/span&gt; http://localhost:8888/_ah/api/&lt;span style=&quot;color:green&quot;&gt;example&lt;/span&gt;/v1/&lt;span style=&quot;color:red&quot;&gt;container&lt;/span&gt;&lt;/span&gt; &lt;/p&gt;&lt;p&gt;&lt;hr&gt;2. An insert method with GET-parameter in addition to object payload &lt;p&gt;&lt;p&gt;&lt;b&gt;CODE&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;http://data.nilzorblog.com/blogposts/rest-at-gae/url-example-3.png&quot;&gt;  &lt;/p&gt;&lt;p&gt;&lt;b&gt;URL&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;span class=&quot;code&quot;&gt;HTTP &lt;span style=&quot;color:blue&quot;&gt;POST&lt;/span&gt; http://localhost:8888/_ah/api/&lt;span style=&quot;color:green&quot;&gt;example&lt;/span&gt;/&lt;span style=&quot;color:orange&quot;&gt;v2&lt;/span&gt;/&lt;span style=&quot;color:red&quot;&gt;container&lt;/span&gt;/&lt;span style=&quot;color:purple&quot;&gt;4381294&lt;/span&gt;&lt;/span&gt; &lt;/p&gt;&lt;p&gt;&lt;hr&gt;3. Remove method  &lt;p&gt;&lt;b&gt;CODE&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;http://data.nilzorblog.com/blogposts/rest-at-gae/url-example-4.png&quot;&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;URL&lt;/b&gt; &lt;p&gt;&lt;span class=&quot;code&quot;&gt;HTTP &lt;span style=&quot;color:blue&quot;&gt;DELETE&lt;/span&gt; http://localhost:8888/_ah/api/&lt;span style=&quot;color:green&quot;&gt;example&lt;/span&gt;/v1/&lt;span style=&quot;color:red&quot;&gt;container&lt;/span&gt;/&lt;span style=&quot;color:purple&quot;&gt;4381294&lt;/span&gt;&lt;/span&gt; &lt;/p&gt;&lt;p&gt;No it&#39;s not a mistake that I&#39;ve now red-boxed the method postfix &quot;Container&quot; in &quot;removeContainer&quot;. &lt;b&gt;The remove method does not follow the same code convention as the others&lt;/B&gt;. Thank you Google. I sincerely hope this is a bug. &lt;hr&gt;&lt;h2&gt;Troubleshooting&lt;/h2&gt;Finally I&#39;d like to mention a couple of pointers as to where to look if you can&#39;t make this work. These are pitfalls I&#39;ve gone into. So, in no particular order: &lt;ul&gt;&lt;li&gt;Look for errors messages in the Jetty error console&lt;br /&gt;
&lt;li&gt;Make sure &lt;span class=&quot;code&quot;&gt;war/WEB-INF/yourapname-v1.api&lt;/span&gt; is autogenerated after each compilation. Try removing the @Named-annotation in front of a random input parameter for a method. You will notice that the .api file is not generated. This will result in &lt;i&gt;all&lt;/i&gt; of your methods returning 404-errors.&lt;br /&gt;
&lt;li&gt;Make sure you always shut down the server before launching a new version on the dev-server. Or else your old code is still running and serving. See illustration:&lt;br /&gt;
&lt;p&gt;&lt;img border=1 src=&quot;http://data.nilzorblog.com/blogposts/rest-at-gae/console.png&quot;&gt;&lt;br /&gt;
&lt;/p&gt;&lt;/ul&gt;&lt;h2&gt;Final words&lt;/h2&gt;I really like the idea of Google pushing their own REST framework for AppEngine. It eliminates one source of dependency problems which frameworks like Jersey and RESTlet gives you. What I don&#39;t like is the poor documentation and the inconsequent code convention. I guess that&#39;s what you get for working with beta software. Just be cautious pushing any code to production knowing this. I&#39;m still going to use this as back-end for my Android software. Solely for the reason that this is the &lt;i&gt;only&lt;/i&gt; REST-framwork I&#39;ve gotten to run on AppEngine. I even went so far as to try Microsoft Azure for Java in desperation, but more on that in another post ;-) &lt;script&gt;/*setupZoom();*/&lt;/script&gt; </content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/1277574751298538912/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2013/02/a-google-cloud-endpoints-hello-world.html#comment-form' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/1277574751298538912'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/1277574751298538912'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2013/02/a-google-cloud-endpoints-hello-world.html' title='A Google Cloud Endpoints Hello-World example in Java using Eclipse'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-6443364967811791833</id><published>2013-01-08T07:30:00.000-08:00</published><updated>2013-02-11T01:34:29.270-08:00</updated><title type='text'>Improving the Generic C# Dictionary with extension methods</title><content type='html'>The &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/xfhwa508.aspx&quot;&gt;Generic Dictionary&lt;/a&gt; in C#/.NET is very versatile and I use it a lot. So often that I found myself writing the same pattern of code around them over and over again. Code I feel should be a part of the class itself. Therefore I&#39;ve taken the liberty of writing a couple of short extension methods that I really think would help clean up and make your code more readable whenever you&#39;re using Dictionaries. Speaking of readability - It&#39;s important to &lt;a href=&quot;http://eli.thegreenplace.net/2013/01/05/understanding-your-own-code/&quot;&gt;understand your own code&lt;/a&gt;.&lt;br /&gt;
&lt;p&gt;The first pattern I often encounter, is checking whether or not a key exists in the dictionary before attempting to retrieve the value. As we know, the dictionary throws an exception if the key does not exist. Yes, I know there is &lt;span class=&quot;code&quot;&gt;TryGetValue&lt;/span&gt;-method, but then you have to meddle with out-parameters and your get-code is already more than one line. The extension method &lt;span class=&quot;code&quot;&gt;GetOrDefault&lt;/span&gt; below aims at solving this. Instead of throwing an exception when the key is not present, it returns the default value of that class. &lt;br /&gt;
&lt;p&gt;&lt;p&gt;The second pattern I often use is also related to non-existent keys. But this time I want to construct a new object if it doesn&#39;t exist, and work with this new object in the code lines to come. There is an elegant solution to this as well using generics, although it will require the value type to be of a class type. See method &lt;span class=&quot;code&quot;&gt;GetOrInsertNew&lt;/span&gt; below on how I solved that in four lines.&lt;br /&gt;
&lt;p&gt;Here is the complete class:&lt;br /&gt;
&lt;p&gt;&lt;pre class=&quot;brush:csharp&quot;&gt;public static class DictionaryExtensions
    {
        /// &amp;lt;summary&amp;gt;
        /// Returns the default value of type U if the key does not exist in the dictionary
        /// &amp;lt;/summary&amp;gt;
        public static U GetOrDefault&amp;lt;T, U&amp;gt;(this Dictionary&amp;lt;T, U&amp;gt; dic, T key)
        {
            if (dic.ContainsKey(key)) return dic[key];
            return default(U);
        }

        /// &amp;lt;summary&amp;gt;
        /// Returns an existing value U for key T, or creates a new instance of type U using the default constructor, 
        /// adds it to the dictionary and returns it.
        /// &amp;lt;/summary&amp;gt;
        public static U GetOrInsertNew&amp;lt;T, U&amp;gt;(this Dictionary&amp;lt;T, U&amp;gt; dic, T key)
            where U : new()
        {
            if (dic.ContainsKey(key)) return dic[key];
            U newObj = new U();
            dic[key] = newObj;
            return newObj;
        }
    }

&lt;/pre&gt;&lt;p&gt;As an example of how using this improves the readability of your code, let&#39;s say you&#39;re building some kind of custom session handling for some sort of service. Using plain Dictionary without the extension, you could implement the GetSession-method like this:&lt;br /&gt;
&lt;p&gt;&lt;pre class=&quot;brush:csharp&quot;&gt;private Dictionary&amp;lt;string, Session&amp;gt; _sessionDic; 

    public Session GetSession(string sessionId)
    {
        if (_sessionDic.ContainsKey(sessionId)) return _sessionDic[sessionId];
        var session = new Session();
        _sessionDic[sessionId] = session;
        return session;
    }      
&lt;/pre&gt;&lt;p&gt;Now using the extension methods, the retrieving code could be reduced to one line:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:csharp&quot;&gt;private Dictionary&amp;lt;string, Session&amp;gt; _sessionDic; 

    public Session GetSession(string sessionId)
    {
        return _sessionDic.GetOrInsertNew(sessionId);
    }
&lt;/pre&gt;&lt;p&gt;Another convenience is that if you are like me and work with other languages that are dynamically typed, like Javascript or PHP, the Dictionary will now behave more like their counterparts &lt;a href=&quot;http://www.w3.org/wiki/Objects_in_JavaScript#Objects_as_associative_arrays&quot;&gt;Associative arrays in Javascript&lt;/a&gt; and &lt;a href=&quot;http://php.net/manual/en/language.types.array.php&quot;&gt;Arrays in PHP&lt;/A&gt;. (Yes I know they&#39;re far from exactly the same, but they have comparable behaviour)&lt;br /&gt;
&lt;p&gt;In summary, this is no sorcery - just a simple tool that I have found to be nice to have in my toolbox, and what I believe to be a good application of extension methods. &lt;br /&gt;
&lt;hr&gt;&lt;p&gt;&lt;b&gt;Update 11th Feb 2013:&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Simen&#39;s suggestion from the comments is implemented and posted to &lt;a href=&quot;https://gist.github.com/Nilzor/4753489&quot;&gt;this public github gist&lt;/A&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/6443364967811791833/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2013/01/improving-generic-c-dictionary-with.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/6443364967811791833'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/6443364967811791833'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2013/01/improving-generic-c-dictionary-with.html' title='Improving the Generic C# Dictionary with extension methods'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-7411559824303387224</id><published>2012-10-18T02:30:00.002-07:00</published><updated>2012-10-18T02:30:36.961-07:00</updated><title type='text'>Lessons learned from my first Windows 8 Metro development project</title><content type='html'>Yesterday I talked at &lt;a href=&quot;http://oslo.nnug.no/&quot;&gt;NNUG Oslo&lt;/a&gt; about my experiences and lessons learned developing my first Windows 8 application Ticki. Coming from a .NET WinForms world, the things that took the most time getting a grip on was the new pattern for asynchronous programming using async await and the &lt;a href=&quot;http://www.microsoft.com/en-us/download/details.aspx?id=19957&quot;&gt;Task Asynchronous Pattern&lt;/a&gt;. An other challenge for me was doing &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/hh848246.aspx&quot;&gt;MVVM&lt;/a&gt; right. I knew the gist of the pattern, but applying it correctly in a Windows 8 context took some learning.&lt;br /&gt;
&lt;br /&gt;
As promised, I leave you here with a link to the slides and also a summary of the resources I link to from that presentation:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
On asynchronous programming&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Lucian Wishik&#39;s talk from NDC 2012: &lt;a href=&quot;http://ndcoslo.oktaset.com/t-4925&quot;&gt;Part 1&lt;/a&gt;, &lt;a href=&quot;http://ndcoslo.oktaset.com/t-4926&quot;&gt;Part 2&lt;/a&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Stephen Toubs &lt;a href=&quot;http://www.microsoft.com/en-us/download/details.aspx?id=19957&quot;&gt;Task Asynchronous Pattern&lt;/a&gt; (TAP) paper&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;http://blogs.msdn.com/b/pfxteam/archive/2012/02/12/10266983.aspx&quot;&gt;Async Semaphore&lt;/a&gt; class by Stephen Toub. (Check out more of his posts, for instance &lt;a href=&quot;http://blogs.msdn.com/b/pfxteam/archive/2012/04/12/10293335.aspx&quot;&gt;his async-await FAQ&lt;/a&gt;, when you&#39;re there!)&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
On MVVM and Databinding&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/hh848246.aspx&quot;&gt;The MVVM Pattern&lt;/a&gt; from Microsoft Patterns and Practices&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://mvvmlight.codeplex.com/&quot;&gt;The MVVM Light Toolkit&lt;/a&gt;. Note: You can also install this via NuGet with &quot;Install-Package MvvmLight&quot;&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Achieving &lt;a href=&quot;http://stackoverflow.com/questions/6002046/binding-visualstatemanager-view-state-to-a-mvvm-viewmodel&quot;&gt;Databound Visual States&lt;/a&gt; in Windows 8 Metro apps.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;More on &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/apps/hh758282&quot;&gt;Attached Properties&lt;/a&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
Creating user controls and getting to know the UI framework&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Scott Guthrie on &lt;a href=&quot;http://weblogs.asp.net/scottgu/pages/silverlight-tutorial-part-7-using-control-templates-to-customize-a-control-s-look-and-feel.aspx&quot;&gt;Control Templates&lt;/a&gt;&lt;br /&gt;
 &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.codeproject.com/Articles/21495/Understanding-the-Visual-Tree-and-Logical-Tree-in&quot;&gt;The Visual Tree vs the Logical Tree&lt;/a&gt; from Josh Smith at Codeproject.com&lt;br /&gt;
 &lt;/li&gt;
&lt;li&gt;Creating &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/apps/hh920267&quot;&gt;Custom dependency properties&lt;/a&gt; (MSDN)&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;
And finally, the slides:
&lt;br /&gt;
&lt;a href=&quot;http://data.nilzorblog.com/blogposts/Ticki-Erfaringer-NNUG-Frode-Nilsen.pptx&quot;&gt;Ticki-Erfaringer-NNUG-Frode-Nilsen.pptx&lt;/a&gt;&lt;br /&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/7411559824303387224/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2012/10/lessons-learned-from-my-first-windows-8.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/7411559824303387224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/7411559824303387224'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2012/10/lessons-learned-from-my-first-windows-8.html' title='Lessons learned from my first Windows 8 Metro development project'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-6021748459575333699</id><published>2012-05-04T07:16:00.004-07:00</published><updated>2012-05-04T07:33:45.185-07:00</updated><title type='text'>Using wget to call WCF services</title><content type='html'>&lt;style&gt;
 .code { background: #DEDEDE; color:black; font-family:monospace }
&lt;/style&gt;
There are a number of general purpose tools created to perform calls to WCF services, like &lt;a href=&quot;http://www.soapui.org/&quot;&gt;SoapUI&lt;/a&gt; and &lt;a href=&quot;http://www.wcfstorm.com&quot;&gt;WCFStorm&lt;/a&gt;. 
Visual Studio also ships with one - &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/bb552364.aspx&quot;&gt;WcfTestClient&lt;/a&gt;, but this one is very simple and has no features for automation. Some times 
you just want to perform a low level call, or you want to make WCF-calls from a BAT/CMD file. Why download and install a multi-megabyte packaget when this should be as simple 
as performing a fairly standard HTTP GET request?
&lt;p&gt;
&lt;a href=&quot;http://www.gnu.org/software/wget/manual/wget.html&quot;&gt;wget&lt;/a&gt; is a utility that should be in any web developer&#39;s tool box. If you&#39;re on linux this is a no-brainer (apt-get install wget), but you can also get this on windows. Heard of
&lt;em&gt;gnuwin32&lt;/em&gt;? You can use the download manager &lt;a href=&quot;http://sourceforge.net/projects/getgnuwin32/&quot;&gt;getgnuwin32&lt;/a&gt; to get the entire package, or you can just download
&lt;a href=&quot;http://gnuwin32.sourceforge.net/packages/wget.htm&quot;&gt;what&#39;s needed&lt;/a&gt; for wget. If not, make sure you download both the binaries and the dependencies zip file.
&lt;p&gt;
&lt;h2&gt;Using BasicHttpBinding (SOAP 1.1)&lt;/h2&gt;
As an example, let&#39;s say you&#39;ve created the following service

&lt;pre class=&quot;brush:csharp&quot;&gt;
    [ServiceContract(Namespace = &quot;http://tepmuri.org/myservice/&quot;)]
    public interface IService
    {
        [OperationContract]
        string Hello(string name);
    }

    public class Service : IService
    {
        public string Hello(string name)
        {
            return &quot;Hello &quot; + name;
        }
    }
&lt;/pre&gt;

It&#39;s a simple Hello World service that takes a string for input and returns one as output. Let&#39;s also make the following assumptions:

&lt;ul&gt;
 &lt;li&gt;You&#39;re serving it at &lt;span class=&quot;code&quot;&gt;http://localhost/Service.svc&lt;/span&gt;
 &lt;li&gt;You&#39;re using &lt;span class=&quot;code&quot;&gt;BasicHttpBinding&lt;/span&gt;
&lt;/ul&gt;

You then need to synthesize the SOAP input XML. If you think that sounds boring, you could always copy it from an actual call made with a thicker client 
 (like a .NET program or WcfTestClinet).
 &lt;a href=&quot;http://www.fiddler2.com/fiddler2/&quot;&gt;Fiddler&lt;/a&gt; can help you with this.
 &lt;p&gt;
For the example service given above under the given circumstances (BasicHttpBinding), this is a valid SOAP 1.1 XML input:

&lt;p&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;
 &amp;lt;s:Envelope xmlns:s=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot;&amp;gt;
  &amp;lt;s:Body&amp;gt;
   &amp;lt;Hello xmlns=&quot;http://tepmuri.org/myservice/&quot;&amp;gt;
    &amp;lt;name&amp;gt;world&amp;lt;/name&amp;gt;
   &amp;lt;/Hello&amp;gt;
  &amp;lt;/s:Body&amp;gt;
 &amp;lt;/s:Envelope&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
Let&#39;s say you&#39;ve saved this text into a file called &lt;i&gt;hello.xml&lt;/i&gt;. To perform the call, execute the following wget command from the command line:
&lt;p&gt;
&lt;div class=&quot;code&quot;&gt;
wget --post-file &quot;hello.xml&quot; --header &quot;content-type: text/xml;charset=utf-8&quot; --header &quot;SOAPAction: http://tepmuri.org/myservice/IService/Hello&quot; http://localhost/Service.svc
&lt;/div&gt;
&lt;p&gt;
There&#39;s really not much to it We need four parameteres
&lt;ol&gt;
 &lt;li&gt;The input XML as a filename
  &lt;li&gt;A HTTP header specifying the content-type
  &lt;li&gt;A HTTP header specifying the SOAP Action name with full namespace
  &lt;li&gt;URL of the service
&lt;/ol&gt;

&lt;p&gt;
 If you&#39;ve done everything correctly, you should get a 200 return code and the SOAP XML Body in the HTTP Body. 
 
&lt;p&gt;
 &lt;h2&gt;Using WsHttpBinding (SOAP 1.2)&lt;/h2&gt;
Now if you&#39;re using WsHttpBinding, you need a slightly more complex input XML. Use this as a starting point:
&lt;p&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;
 &amp;lt;s:Envelope xmlns:s=&quot;http://www.w3.org/2003/05/soap-envelope&quot; xmlns:a=&quot;http://www.w3.org/2005/08/addressing&quot;&amp;gt;
  &amp;lt;s:Header&amp;gt;
   &amp;lt;a:Action s:mustUnderstand=&quot;1&quot; &amp;gt;http://tepmuri.org/myservice/IService/Hello&amp;lt;/a:Action&amp;gt;
   &amp;lt;a:MessageID&amp;gt;urn:uuid:149c449f-0593-416b-ae1f-b73308a6e2d2&amp;lt;/a:MessageID&amp;gt;
   &amp;lt;a:ReplyTo&amp;gt;
    &amp;lt;a:Address&amp;gt;http://www.w3.org/2005/08/addressing/anonymous&amp;lt;/a:Address&amp;gt;
   &amp;lt;/a:ReplyTo&amp;gt;
   &amp;lt;a:To s:mustUnderstand=&quot;1&quot;&amp;gt;http://localhost/Service.svc&amp;lt;/a:To&amp;gt;
  &amp;lt;/s:Header&amp;gt;
  &amp;lt;s:Body&amp;gt;
   &amp;lt;Hello xmlns=&quot;http://tepmuri.org/myservice/&quot;&amp;gt;
    &amp;lt;name&amp;gt;world&amp;lt;/name&amp;gt;
   &amp;lt;/Hello&amp;gt;
  &amp;lt;/s:Body&amp;gt;
 &amp;lt;/s:Envelope&amp;gt;

&lt;/pre&gt;

In addition you&#39;ll need to change the content-type HTTP header of the wget command to the following:
&lt;p&gt;
 &lt;pre class=&quot;code&quot;&gt;-header &quot;Content-Type: application/soap+xml; charset=utf-8&quot; 
&lt;/pre&gt;
&lt;p&gt;
 A couple of more wget paramteres that might come handy:
 &lt;ul&gt;
  &lt;li&gt;&lt;b&gt;HTTPS:&lt;/b&gt; If you&#39;re exposing the service with HTTPS security and you have a temporary SSL Certificate, use &lt;span class=&quot;code&quot;&gt;--no-check-certificate &lt;/span&gt;
 &lt;li&gt;&lt;b&gt;Proxy:&lt;/b&gt; Wget takes proxy credentials on the command line, but the URL is specified by an environment variable named http_proxy. 
    Running  &lt;span class=&quot;code&quot;&gt;SET http_proxy=localhost:8888&lt;/span&gt; on the command line before wget will redirect all commands through a proxy (like i.e. fiddler)
    &lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/6021748459575333699/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2012/05/using-wget-to-call-wcf-services.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/6021748459575333699'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/6021748459575333699'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2012/05/using-wget-to-call-wcf-services.html' title='Using wget to call WCF services'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-6499806868954176969</id><published>2011-11-15T09:05:00.000-08:00</published><updated>2015-01-31T05:22:09.795-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="bre"/><category scheme="http://www.blogger.com/atom/ns#" term="rules"/><category scheme="http://www.blogger.com/atom/ns#" term="WF3"/><category scheme="http://www.blogger.com/atom/ns#" term="WF4"/><category scheme="http://www.blogger.com/atom/ns#" term="Workflow"/><title type='text'>Using WF4 as a Business Rule Engine</title><content type='html'>&lt;h3&gt;Introduction&lt;/h3&gt;A project at work forced me to get up to speed on Windows Workflow Foundation (WF) quickly. My boss wanted to use it as a business  rule engine where the end user could edit the rules themselves. They didn&#39;t necessarily need full flexibility on the editing, but the core parameters of the rules had to be editable. Now there&#39;s probably hundred ways to approach this, and many ways to do it without using Workflow Foundation, but I decided do a proof of concept doing so. &lt;p&gt;I then came over Christophe Geers&#39; Blog and the article &lt;a href=&quot;http://cgeers.com/2008/01/26/using-rules-outside-of-a-workflow&quot;&gt;Using Rules outside of a Workflow&lt;/A&gt;. This was the kind of kick-start I needed - or so I thought, until I noticed it targets WF3 (Workflow for .NET 3.5). Now I &lt;em&gt;could&lt;/em&gt; go on and use WF3, but some Googling and reading lead me to believe i would be better prepared for the future using WF4 instead*. In this article I will implement the same application as Christophe Geers did, but in Workflow 4.  &lt;p&gt;*) &lt;i&gt;You may argue against this in the comment field if you like - I&#39;m still not sure this is an obvious choice.&lt;/i&gt;  &lt;h3&gt;Workflow 3 vs 4&lt;/h3&gt;So what has changed? A lot. Microsoft has rewritten the Workflow framework quite extensively from WF3 to WF4, and the way you work with Rules is fundamentally changed. Long story short, I feel they&#39;ve tried to generalize the concept of an element in a workflow to the point where &quot;everything is an apple&quot;. Maybe they&#39;ve succeeded - I really haven&#39;t worked long enough with the framework to comment on this. Anyway, a &lt;em&gt;Rule&lt;/em&gt; is now a basically an &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.workflow.componentmodel.activity.aspx&quot;&gt;Activity&lt;/a&gt; configured accordingly. The &lt;a href =&quot;http://msdn.microsoft.com/en-us/library/system.workflow.activities.rules.rule.aspx&quot;&gt;Rule&lt;/a&gt; class is obsolete. I will not go into detail on the changes - Microsoft have published a 17 page document comparing how to use the concept of Rules in the document &lt;em&gt;WF Guidance: Rules&lt;/em&gt; which is a part of the &lt;a href=&quot;http://msdn.microsoft.com/library/ee264175.aspx&quot;&gt;WF4 Migration guide&lt;/A&gt; &lt;h3&gt;The Salutation Resolver Solution&lt;/h3&gt;Christophe Geers implemented a rule set in WF3 which basically decides the correct salutation in a letter for a person given some basic properties about that person. I&#39;m not going to go into the same level of detail regarding the problem domain as Geers did, instead I&#39;ll focus on how to implement it in WF4. For reference, go to &lt;a href=&quot;http://cgeers.com/2008/01/26/using-rules-outside-of-a-workflow/#personclass&quot;&gt;his blog entry&lt;/a&gt; at any time. This table will describe the expected result though:  &lt;p&gt;&lt;table class=&quot;grid-1&quot;&gt;&lt;tr&gt;&lt;th&gt;Gender&lt;th&gt;Age&lt;th&gt;Married&lt;th style=&quot;text-align:center&quot;&gt;Salutation&lt;/tr&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;M&lt;td&gt;&amp;gt;18&lt;td&gt;Yes/No&lt;td style=&quot;text-align:center&quot;&gt;Mr&lt;/tr&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;F&lt;td&gt;&amp;gt;18&lt;td&gt;No&lt;td style=&quot;text-align:center&quot;&gt;Miss&lt;/tr&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;F&lt;td&gt;&amp;gt;18&lt;td&gt;Yes&lt;td style=&quot;text-align:center&quot;&gt;Mrs&lt;/tr&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;F/M&lt;td&gt;&amp;lt;18&lt;td&gt;Yes/No&lt;td style=&quot;text-align:center&quot;&gt;To the parents of&lt;/tr&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;/table&gt;&lt;p&gt;The solution will be divided into three projects: &lt;ol&gt;&lt;li&gt;A shared library with the business entities&lt;/li&gt;
&lt;li&gt;A Forms project which take input and allow you to edit rules&lt;/li&gt;
&lt;li&gt;A Workflow Activity project. This is where the juice is. &lt;/ol&gt;&lt;p&gt;&lt;b&gt;The Forms project&lt;/b&gt; contains two forms. The parameter input form looks like this: &lt;p&gt;&lt;img src=&quot;http://data.nilzorblog.com/wf4-salutationrules/mainform.png&quot;&gt; &lt;p&gt;It will allow you to change the input parameters and see how the result of the workflow execution changes accordingly. The second form is for altering the business rules runtime. I will come back to that later.  &lt;p&gt;The &lt;b&gt;shared library&lt;/b&gt; contains two important classes - Person.cs, which is basically identical to the one from Geers&#39; blog, and SalutationAssignmentRule.cs which is a wrapper over the rules we define, and the core of what we will expose to the end user.   &lt;p&gt;The &lt;b&gt;Activity project&lt;/b&gt; contains logic and data for executing the business rules in one of three ways: &lt;ol&gt;&lt;li&gt;From a Workflow diagram designed with the Visual Studio Designer. &lt;/li&gt;
&lt;li&gt;From a hard-coded workflow where all the logic is written in C# code&lt;/li&gt;
&lt;li&gt;From a dynamic workflow where the workflow logic is generated from user input by C# code&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;#1 is cool. The designer produces XAML of the workflow (or &quot;business rules&quot;), which is suited for persitance and to a certain degree modification. I didn&#39;t really see my endusers editing XAML or using Visual Studio to change the business rules though, so this option was not for me. &lt;p&gt;#2 is cooler. Here I prove that the same can be done in code. Articles like &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/dd807392.aspx&quot;&gt;DynamicAcitivty Creation&lt;/A&gt; and Kushal Shah&#39;s &lt;a hreF=&quot;http://blogs.msdn.com/b/kushals/archive/2009/10/26/adding-variables-expressions-and-bindings-programmatically.aspx&quot;&gt;Adding Variables, Expressions and Bindings Programmatically&lt;/a&gt; helped me accomplish this, but the way I implemented it,  the rules are pretty static. &lt;p&gt;#3: Now we&#39;re getting somewhere. By adding a layer on top of the code in #2, we can expose part of the rules to the end users. In this example I go as far as exposing the Visual Basic-style condition statements and the if-then-else-assignments to the user interface. This may be overkill for my end users, but I&#39;m showing that the flexibility is there. See screenshot below. &lt;p&gt;&lt;img src=&quot;http://data.nilzorblog.com/wf4-salutationrules/rulesform.png&quot;&gt;  &lt;i&gt;In this DataGridView you can edit the rules runtime.&lt;/i&gt;&lt;/br&gt;   &lt;h3&gt;The implementation&lt;/h3&gt;I will focus on solution #3 from last chapter - where dynamic rules are used. For the other methods, download view the solution yourself (link at bottom). &lt;p&gt;First, the &quot;dumb&quot; business classes: &lt;p&gt;Here is the gist of Person.cs. -Only syntactically altered from Geers&#39; blog: &lt;pre class=&quot;brush:csharp&quot;&gt;public class Person
  {
     #region Properties
     public string Name { get; set; }
     public string Firstname { get; set; }
     public DateTime BirthDate { get; set; }
     public string Gender { get; set; }
     public bool Married { get; set; }
     public string Salutation { get; set; }
     // Read-only properties:
     public Int32 Age { get { return CalculateAge(); } }
     public Boolean Minor { get { return (Age &lt; 18); } }
     // Methods
     private bool CalculateAge() { /* Implementation */ }
  }
&lt;/pre&gt;
&lt;p&gt;Then there is the class for storing the business rules. I need to wrap the complex structure of activities, sequences and arguments from the framwork in a manner that is easier presented in a user interface. In this solution I bind a list of these objects directly to the datagrid.
&lt;pre class=&quot;brush:csharp&quot;&gt;public class SalutationAssignmentRule
    {
        public string Condition { get; set; }
        public int Priority { get; set; }
        public string ThenValue { get; set; }
        public string ElseValue { get; set; }
        public string TargetParameter { get; set; }

        public SalutationAssignmentRule(int priority, string condition, string thenValue, string elseValue = null)
        {
            TargetParameter = &quot;Person.Salutation&quot;; // Could be configurable
            Condition = condition;
            Priority = priority;
            ThenValue = thenValue;
            ElseValue = elseValue;
        }
    }
&lt;/pre&gt;&lt;p&gt;The ActivityLibrary projects is where the magic happens, specifically in SalutationRuleGeneratorDynamic.cs and RuleConverter.cs. The latter converts Rules in the form of SalutationAssignmentRule-objects to WF4 activity objects of type &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.activities.statements.if.aspx&quot;&gt;If&lt;/A&gt;, which are a subclass of the &quot;everything-is-an-apple&quot;-&lt;a href=&quot;&quot;&gt;Action&lt;/a&gt; class.
&lt;p&gt;RuleConverter.cs:
&lt;pre class=&quot;brush:csharp&quot;&gt;public class RuleConverter
  {
      internal static Activity ToIfActivity(SalutationAssignmentRule inRule)
      {
          var condition = new VisualBasicValue&lt;bool&gt;(inRule.Condition);
          var ifActivity = new If(new InArgument&lt;bool&gt;(condition));
          ifActivity.Then = new Assign&lt;string&gt;
          {
              To = new OutArgument&lt;string&gt;(new VisualBasicReference&lt;string&gt;(inRule.TargetParameter)),
              Value = new InArgument&lt;string&gt;(inRule.ThenValue)
          };
          if (inRule.ElseValue != null)
          {
              ifActivity.Else = new Assign&lt;string&gt;
              {
                  To = new OutArgument&lt;string&gt;(new VisualBasicReference&lt;string&gt;(inRule.TargetParameter)),
                  Value = new InArgument&lt;string&gt;(inRule.ElseValue)
              };
          }
          return ifActivity;
      }
  }
 &lt;/pre&gt;&lt;p&gt;Note how the condition, which is a string sounding something like &lt;i&gt;Person.Gender = &quot;Male&quot;&lt;/i&gt;, is input to the If-class directly. By wrapping it in a VisualBasicValue&lt;bool&gt;, it will be interpreted runtime. 
  
  &lt;p&gt;Now there&#39;s a caveat here: The root Workflow object needs to have a Workflow-property set, indicating that VB-statements will be present in the Workflow. A method to add such a parameter to an Activity is implemented in Common.cs:
  &lt;pre class=&quot;brush:csharp&quot;&gt;internal static void AddVbSetting(Activity activity)
  {
      var settings = new VisualBasicSettings {
          ImportReferences = { new VisualBasicImportReference {
              Assembly = typeof(Person).Assembly.GetName().Name,
              Import = typeof(Person).Namespace } } };
      VisualBasic.SetSettings(activity, settings);
  }
 &lt;/pre&gt;If you look at the Visual Studio-generated XAML for the SalutationRules workflow, you will find the same setting generated there, in the tag &amp;lt;mva:VisualBasic.Settings&amp;gt;.
 &lt;p&gt;Going further up the implementation chain, we have the core Workflow generator class in SalutationRuleGeneratorDynamic.cs:
 &lt;pre class=&quot;brush:csharp&quot;&gt;public static Activity CreateSalutationRules(List&lt;salutationassignmentrule&gt; rules)
  {
      var inProperty = new DynamicActivityProperty
      {
          Name = &quot;Person&quot;,
          Type = typeof(InArgument&lt;person&gt;)
  
      };
      var activity = new DynamicActivity() { Properties = { inProperty } };
      Common.AddVbSetting(activity);
  
      var sequence = new Sequence();
      activity.Implementation = () =&gt; sequence;
  
      // Sort descending - those added first are lowest priority
      var sortedRules = rules.OrderByDescending(p =&gt; p.Priority).ToList();
      
      // Convert to if-activities and add to sequence
      foreach (var inRule in sortedRules)
      {
          var outRule = RuleConverter.ToIfActivity(inRule);
          sequence.Activities.Add(outRule);
      }
  
      return activity;
  }
&lt;/pre&gt;&lt;/p&gt;The key thing to notice here is how I order the rules by priority to emulate the Priority property of the Rule class of WF3. When you emulate Rules by using a flat list of If-activities as I do here, you get implicit priority by the order of which you add the If&#39;s to the Sequence object.
 
&lt;p&gt;Finally there is the invocation code. In WF3, you&#39;d instantiate a &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.workflow.activities.rules.ruleexecution.aspx&quot;&gt;RuleExecution&lt;/a&gt; class followed by an Execute. In WF4 the equivalent is the static method &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.activities.workflowinvoker.aspx&quot;&gt;WorkflowInvoker.Invoke()&lt;/A&gt;. Again, this is a general Workflow executer meant for everyone - not just for us weirdos using WF4 as a Business Rule Engine. 
&lt;p&gt;&lt;pre class=&quot;brush:csharp&quot;&gt;private void ExecuteRules(Activity activity, Person person)
    {
        var input = new Dictionary&lt;string, object&gt;();
        input.Add(&quot;Person&quot;, person);
        WorkflowInvoker.Invoke(activity, input);
    }
&lt;/pre&gt;&lt;p&gt;&lt;h3&gt;Persisting code-generated workflows&lt;/h3&gt;Before I round up, I&#39;d like to mention that if you want to generate XAML from the code-generated activities for storage or transport purposes, you&#39;re just a small step away. I didn&#39;t include the code for it in my solution, but the key is to swap the DynamicActivity-instantiation in the CreateSalutationRules-method with a ActivityBuilder-class. The article &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ff458319.aspx&quot;&gt;Serializing workflows and Activities to and from XAML&lt;/a&gt; illustrates how to to this. You will have to do some minor syntactical changes in the CreateSalutationRules-method for it to compile, and also probably have to go thorugh a serialization-deserializiation-process before ending up with an executable Workflow. 

&lt;h3&gt;In closing&lt;/h3&gt;To summarize - yes you can implement Rules in WF4. Is it easier than in WF3? I don&#39;t think so. Is it faster? I don&#39;t know. Microsoft says it is. Is it better? Maybe. Depends on what your needs are. In some regards, WF4 have actually less functionality than the Rules in WF3 - &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/aa349441(v=vs.90).aspx&quot;&gt;forward chaining of rules&lt;/a&gt; is an example of functionality you will NOT get by using WF4 as a BRE. In other areas, WF4 will provide you with more functionality though. The &quot;rules&quot; are no longer restricted to the If-then-else-structure of WF3. You can define a rule as any activity in the Workflow namespace. For the example Christophe Geers and I presented, the differences would not matter much though. Others will have to answer for more complex problem domains.
&lt;p&gt;&lt;h3&gt;Downloads&lt;/h3&gt;Either clone the &lt;a href=&quot;https://github.com/Nilzor/wf4-rule-engine&quot;&gt;repo&lt;/a&gt; by running this command: &lt;p&gt;&lt;div class=&#39;code&#39;&gt;git clone https://github.com/Nilzor/wf4-rule-engine.git&lt;/div&gt;&lt;/p&gt;&lt;p&gt;...or download this ZIP (VS2010 solution): &lt;a href=&quot;http://data.nilzorblog.com/wf4-salutationrules/WF4-SalutationRules.zip&quot;&gt;WF4-SalutationRules.zip&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;hr&gt;&lt;b&gt;&lt;i&gt;Update 25th Nov 2011:&lt;/i&gt;&lt;/b&gt;
Turns out there&#39;s a better way to create the dynamic activity when you have static input- and output parameters as in this case. By creating a class that inherits Activity, you get to create the parameters as standard C# properties instead of generating InArgument-objects that must manually be added to the Properties collection of the Activity class. &lt;p&gt;Updated class for the dynamic activity: &lt;a href=&quot;https://gist.github.com/1393205&quot;&gt;DynamicSalutationRulesActivity.cs&lt;/A&gt; (replaces SalutationRuleGeneratorSynamic)
&lt;p&gt;Thanks goes out to Willem Meints and his blog for this knowledge :) He has a good three-post article about different ways of creating dynamic activities here: &lt;a href=&quot;http://blogs.infosupport.com/building-dynamic-activities-in-workflow-foundation-4/&quot;&gt;part one&lt;/a&gt; - &lt;a href=&quot;http://blogs.infosupport.com/building-dynamic-activities-in-workflow-foundation-4-part-2/&quot;&gt;two&lt;/a&gt; - &lt;a href=&quot;http://blogs.infosupport.com/building-dynamic-activities-in-workflow-foundation-4-part-3/&quot;&gt;three&lt;/a&gt;. (How come I find all the good articles about WF4 in the Benelux-lands? :p) 
&lt;hr&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/6499806868954176969/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2011/11/using-wf4-as-rule-engine.html#comment-form' title='40 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/6499806868954176969'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/6499806868954176969'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2011/11/using-wf4-as-rule-engine.html' title='Using WF4 as a Business Rule Engine'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>40</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-9025144066521456094</id><published>2011-10-01T10:11:00.000-07:00</published><updated>2011-10-01T10:11:51.454-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="andorid"/><category scheme="http://www.blogger.com/atom/ns#" term="gogtasks"/><category scheme="http://www.blogger.com/atom/ns#" term="google"/><category scheme="http://www.blogger.com/atom/ns#" term="gtasks"/><category scheme="http://www.blogger.com/atom/ns#" term="tasks"/><title type='text'>Synchronize your Outlook tasks with Android</title><content type='html'>&lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://data.nilzorblog.com/scripts/jquery.thumbhover.js&quot;&gt;&lt;/script&gt;
&lt;style&gt;
 span.sync-iphone img 
 { 
  margin-bottom:2px; 
  margin-top:10px;
 }
 .bordered
 {  
  border: 1px #b0b0b0 solid;
 }
 .caption
 { 
  font-size: 12px; 
  font-style: italic;
 }
 .padded { 
  padding-left:10px;
  padding-right:10px;
 }
&lt;/style&gt;
&lt;span class=&quot;sync-iphone&quot; &gt;
 &lt;div style=&quot;float:right; padding-left:15px;padding-right:10px;background:#ddd; border:1px #aaa solid&quot;&gt;
  &lt;img src=&quot;http://data.nilzorblog.com/sync-tasks-iphone/tasks-gmail-th.png&quot;&gt;&lt;br&gt;
  &lt;div class=&quot;caption&quot;&gt;The task list in GMail&lt;/div&gt;
  &lt;img src=&quot;http://data.nilzorblog.com/sync-tasks-iphone/tasks-calendar-th.png&quot;&gt;&lt;br&gt;
  &lt;div class=&quot;caption&quot;&gt;The tasks list in Google Calendar&lt;/div&gt;
  &lt;img src=&quot;http://data.nilzorblog.com/sync-tasks-iphone/tasks-canvas-th.png&quot;&gt;
  &lt;div class=&quot;caption&quot;&gt;The Google Canvas web-interface for tasks&lt;/div&gt;
  &lt;img src=&quot;http://data.nilzorblog.com/sync-tasks-iphone/android-widget-th.png&quot;&gt;
  &lt;div class=&quot;caption&quot;&gt;GTasks widget on an Android phone&lt;/div&gt;
  &lt;br&gt;  
 &lt;/div&gt;
 &lt;div style=&quot;&quot;&gt;
  There is no native way of synchronizing your Outlook tasks to an Android-based phone or pad directly as of today. You can synchronize your e-mail and calendar using the Outlook Exchange protocol, but that protocol does not support tasks. Many developers have made efforts to work around that issue and created third party tools that allow you to synchronize via cloud services such as &lt;a href=&quot;http://www.rememberthemilk.com/&quot;&gt;Remember the Milk&lt;/a&gt; or &lt;a href=&quot;http://www.toodledo.com/&quot;&gt;ToodleDo&lt;/a&gt;. These services will all get the job done, but if you are a &lt;a href=&quot;http://www.gmail.com&quot;&gt;Google Mail&lt;/A&gt; and &lt;a href=&quot;http://www.google.com/calendar&quot;&gt;Calendar&lt;/a&gt; user like me, the more natural cloud service for my tasks would be the Google Task list. This is the alternative I will present in this article.
  &lt;p&gt;

  The Google Task list is a service that is available both through GMail and the Calendar, or at the standalone interfaces &lt;a href=&quot;http://mail.google.com/tasks/canvas&quot;&gt;Google Tasks Canvas&lt;/a&gt; or the &lt;a 
href=&quot;http://mail.google.com/tasks/ig&quot;&gt;Hand-Held Device Interface&lt;/a&gt;. See screenshots to the right. To synchronize with Outlook using Google Tasks as the &quot;man in the middle&quot;, you&#39;ll need two applications: one at the iPhone and one at the computer running Outlook.
&lt;p&gt;
 &lt;h3&gt;1. At the Android device&lt;/h3&gt;
There are several tools for Android devices that will let you work with Google Tasks, for example 
&lt;a href=&quot;https://market.android.com/details?id=org.dayup.gtask&quot;&gt;GTasks&lt;/a&gt;
and
&lt;a href=&quot;https://market.android.com/details?id=com.tinjasoft.tasks&quot;&gt;Google Tasks Organizer&lt;/a&gt; (GTO).
I&#39;m using GTask, so that&#39;s what I&#39;ll be using as an example here. I&#39;m sure there are even more alternatives, but GTasks gets the job done. The free version is ad-based, but you can upgrade for ~$8. That said, the price of GTO is only $3, but it does not have widget support (as of now). A widget is really useful if you ask me. Then you can have the most pressing task list &quot;just a flick away&quot; at one of your home screens. See the screenshot to the right for an example.

 &lt;h3&gt;2. At the computer&lt;/h3&gt;
 Here the only tool I know of is called &lt;a href=&quot;http://www.gogtasks.com&quot;&gt;GogTasks&lt;/a&gt;. Incidentally, I&#39;m also the developer of this tool, so a little disclaimer goes out right now ;-) They say that all developing projects starts because the developer wants to &quot;scratch their own itch&quot;, and that is also the case here. I needed to get my daily life organized, not forgetting things that needed to &lt;a href=&quot;http://en.wikipedia.org/wiki/Getting_Things_Done&quot;&gt;get done&lt;/A&gt;, and I discovered the lack of a sync tool between Outlook og Google was a hindrance. So I made GogTasks, and this tool will be the second element in getting the iPhone-Google-Outlook-sync up and running. 
 &lt;p&gt;
 GogTasks works for both Outlook 2003, 2007 and 2010. You can set it up to synchronize at a regular interval so you basically don&#39;t need to worry about it being there at all. 
&lt;h3&gt;Putting it all together&lt;/h3&gt;
As soon as you&#39;ve configured GTasks (or GTO) and GogTasks to sync against your GMail account, there&#39;s not really much to it. Synchornize your tasks, and they will be available wherever you are - on the bus with your phone/pad, by your work computer with Outlook, or from the internet café in Amsterdam when your there to... visit your aunt.
&lt;p&gt;
One thing you should be aware of though, is that Outlook have a much more rich concept of a &quot;Task&quot;, with things such as recurring tasks and assigning it to multiple categories. Read about how GogTasks handles that &lt;a href=&quot;http://www.gogtasks.com/limitations.php&quot;&gt;here&lt;/a&gt;
&lt;p&gt;
The final picture:
 &lt;table width=&quot;98%&quot;&gt;
  &lt;tr&gt;
   &lt;td width=&quot;40%&quot;&gt;&amp;nbsp;&lt;/td&gt;
   &lt;td class=&quot;padded&quot;&gt;
    &lt;img class=&quot;bordered&quot; src=&quot;http://data.nilzorblog.com/sync-tasks-iphone/sync-android-th.png&quot;&gt;&lt;br&gt;
    &lt;div class=&quot;caption&quot;&gt;The device&lt;/div&gt;
   &lt;/td&gt;
   &lt;td&gt;&lt;img src=&quot;http://data.nilzorblog.com/sync-tasks-iphone/left-right-arrow-s.png&quot; &gt;&lt;/td&gt;
   &lt;td class=&quot;padded&quot;&gt;
    &lt;img src=&quot;http://data.nilzorblog.com/sync-tasks-iphone/sync-canvas-th.png&quot;&gt;&lt;br&gt;
    &lt;div class=&quot;caption&quot;&gt;Google&lt;/div&gt;
   &lt;/td&gt;   
   &lt;td&gt;&lt;img src=&quot;http://data.nilzorblog.com/sync-tasks-iphone/left-right-arrow-s.png&quot; &gt;&lt;/td&gt;
   &lt;td class=&quot;padded&quot;&gt;
    &lt;img src=&quot;http://data.nilzorblog.com/sync-tasks-iphone/sync-outlook-th.png&quot;&gt;&lt;br&gt;
    &lt;div class=&quot;caption&quot;&gt;Outlook&lt;/div&gt;
   &lt;/td&gt;
   &lt;td width=&quot;40%&quot;&gt;&amp;nbsp;&lt;/td&gt;
  &lt;/tr&gt;
 &lt;/table&gt; 
 &lt;/div&gt;
 &lt;p&gt;
&lt;/span&gt;

&lt;script type=&quot;text/javascript&quot;&gt;
 $(function(){
  $(&quot;img[src*=&#39;-th.png&#39;]&quot;).thumbPopup({imgSmallFlag: &quot;-th&quot;, imgLargeFlag: &quot;&quot;});
 });
&lt;/script&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/9025144066521456094/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2011/10/synchronize-your-outlook-tasks-with_01.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/9025144066521456094'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/9025144066521456094'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2011/10/synchronize-your-outlook-tasks-with_01.html' title='Synchronize your Outlook tasks with Android'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-2990406276560063935</id><published>2011-10-01T08:07:00.000-07:00</published><updated>2011-10-01T10:12:14.900-07:00</updated><title type='text'>Synchronize your Outlook tasks with iPhone</title><content type='html'>&lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://data.nilzorblog.com/scripts/jquery.thumbhover.js&quot;&gt;&lt;/script&gt;
&lt;style&gt;
 span.sync-iphone img 
 { 
  margin-bottom:2px; 
  margin-top:10px;
 }
 .bordered
 {  
  border: 1px #b0b0b0 solid;
 }
 .caption
 { 
  font-size: 12px; 
  font-style: italic;
 }
 .padded { 
  padding-left:10px;
  padding-right:10px;
 }
&lt;/style&gt;
&lt;span class=&quot;sync-iphone&quot;&gt;
&lt;div style=&quot;float:right; padding-left:15px;padding-right:10px;background:#ddd; border:1px #aaa solid&quot;&gt;
  &lt;img src=&quot;http://data.nilzorblog.com/sync-tasks-iphone/tasks-gmail-th.png&quot;&gt;&lt;br&gt;
  &lt;div class=&quot;caption&quot;&gt;The task list in GMail&lt;/div&gt;
  &lt;img src=&quot;http://data.nilzorblog.com/sync-tasks-iphone/tasks-calendar-th.png&quot;&gt;&lt;br&gt;
  &lt;div class=&quot;caption&quot;&gt;The tasks list in Google Calendar&lt;/div&gt;
  &lt;img src=&quot;http://data.nilzorblog.com/sync-tasks-iphone/tasks-canvas-th.png&quot;&gt;
  &lt;div class=&quot;caption&quot;&gt;The Google Canvas web-interface for tasks&lt;/div&gt;
  &lt;br&gt;  
 &lt;/div&gt;
 &lt;div style=&quot;&quot;&gt;
  There is no native way of synchronizing your Outlook tasks to iPhone directly as of today. You can synchronize your e-mail and calendar using the Outlook Exchange protocol, but that protocol does not support tasks. Many developers have made efforts to work around that issue and created third party tools that allow you to synchronize via cloud services such as &lt;a href=&quot;http://www.rememberthemilk.com/&quot;&gt;Remember the Milk&lt;/a&gt; or &lt;a href=&quot;http://www.toodledo.com/&quot;&gt;ToodleDo&lt;/a&gt;. These services will all get the job done, but if you are a &lt;a href=&quot;http://www.gmail.com&quot;&gt;Google Mail&lt;/A&gt; and &lt;a href=&quot;http://www.google.com/calendar&quot;&gt;Calendar&lt;/a&gt; user like me, the more natural cloud service for my tasks would be the Google Task list. This is the alternative I will present in this article.
  &lt;p&gt;

  The Google Task list is a service that is available both through GMail and the Calendar, or at the standalone interfaces &lt;a href=&quot;http://mail.google.com/tasks/canvas&quot;&gt;Google Tasks Canvas&lt;/a&gt; or the &lt;a 
href=&quot;http://mail.google.com/tasks/ig&quot;&gt;Hand-Held Device Interface&lt;/a&gt;. See screenshots to the right. To synchronize with Outlook using Google Tasks as the &quot;man in the middle&quot;, you&#39;ll need two applications: one at the iPhone and one at the computer running Outlook.
&lt;p&gt;
 &lt;h3&gt;1. At the iPhone&lt;/h3&gt;
There are several tools for iPhone that will let you work with Google Tasks, for example 
&lt;a href=&quot;http://www.geetasks.com/&quot;&gt;GeeTasks&lt;/a&gt;
or
&lt;a href=&quot;http://itunes.apple.com/us/app/gotasks-google-tasks-client/id389113399?mt=8&quot;&gt;GoTasks&lt;/a&gt;. I&#39;ve tried GoTasks, so that&#39;s what I&#39;ll be using as an example here. I&#39;m sure you can find other alternatives if you search for it, but I&#39;m not sure you&#39;ll really need one. GoTasks gets the job done and has a good and intuitive user interface. This, and it&#39;s free!

 &lt;h3&gt;2. At the computer&lt;/h3&gt;
 Here the only tool I know of is called &lt;a href=&quot;http://www.gogtasks.com&quot;&gt;GogTasks&lt;/a&gt;. Incidentally, I&#39;m also the developer of this tool, so a little disclaimer goes out right now ;-) They say that all developing projects starts because the developer wants to &quot;scratch their own itch&quot;, and that is also the case here. I needed to get my daily life organized, not forgetting things that needed to &lt;a href=&quot;http://en.wikipedia.org/wiki/Getting_Things_Done&quot;&gt;get done&lt;/A&gt;, and I discovered the lack of a sync tool between Outlook og Google was a hindrance. So I made GogTasks, and this tool will be the second element in getting the iPhone-Google-Outlook-sync up and running. 
 &lt;p&gt;
 GogTasks works for both Outlook 2003, 2007 and 2010. You can set it up to synchronize at a regular interval so you basically don&#39;t need to worry about it being there at all. 
&lt;h3&gt;Putting it all together&lt;/h3&gt;
As soon as you&#39;ve configured GoTasks and GogTasks to sync against your GMail account, there&#39;s not really much to it. Synchornize your tasks, and they will be available wherever you are - on the bus with your iPhone, by your work computer with Outlook, or from the internet café by the beach when you&#39;re on vacation (not that you&#39;d really want to get anything done at this time :-). 
&lt;p&gt;
One thing you should be aware of though, is that Outlook have a much more rich concept of a &quot;Task&quot;, with things such as recurring tasks and assigning it to multiple categories. Read about how GogTasks handles that &lt;a href=&quot;http://www.gogtasks.com/limitations.php&quot;&gt;here&lt;/a&gt;
&lt;p&gt;
The final picture:
 &lt;table width=&quot;98%&quot;&gt;
  &lt;tr&gt;
   &lt;td width=&quot;40%&quot;&gt;&amp;nbsp;&lt;/td&gt;
   &lt;td class=&quot;padded&quot;&gt;
    &lt;img class=&quot;bordered&quot; src=&quot;http://data.nilzorblog.com/sync-tasks-iphone/sync-iphone-th.png&quot;&gt;&lt;br&gt;
    &lt;div class=&quot;caption&quot;&gt;Your iPhone&lt;/div&gt;
   &lt;/td&gt;
   &lt;td&gt;&lt;img src=&quot;http://data.nilzorblog.com/sync-tasks-iphone/left-right-arrow-s.png&quot; &gt;&lt;/td&gt;
   &lt;td class=&quot;padded&quot;&gt;
    &lt;img src=&quot;http://data.nilzorblog.com/sync-tasks-iphone/sync-canvas-th.png&quot;&gt;&lt;br&gt;
    &lt;div class=&quot;caption&quot;&gt;Google&lt;/div&gt;
   &lt;/td&gt;   
   &lt;td&gt;&lt;img src=&quot;http://data.nilzorblog.com/sync-tasks-iphone/left-right-arrow-s.png&quot; &gt;&lt;/td&gt;
   &lt;td class=&quot;padded&quot;&gt;
    &lt;img src=&quot;http://data.nilzorblog.com/sync-tasks-iphone/sync-outlook-th.png&quot;&gt;&lt;br&gt;
    &lt;div class=&quot;caption&quot;&gt;Outlook&lt;/div&gt;
   &lt;/td&gt;
   &lt;td width=&quot;40%&quot;&gt;&amp;nbsp;&lt;/td&gt;
  &lt;/tr&gt;
 &lt;/table&gt; 
 &lt;/div&gt;
 &lt;p&gt;
&lt;/span&gt;

&lt;script type=&quot;text/javascript&quot;&gt;
 $(function(){
  $(&quot;img[src*=&#39;-th.png&#39;]&quot;).thumbPopup({imgSmallFlag: &quot;-th&quot;, imgLargeFlag: &quot;-m&quot;});
 });
&lt;/script&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/2990406276560063935/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2011/10/synchronize-your-outlook-tasks-with.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/2990406276560063935'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/2990406276560063935'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2011/10/synchronize-your-outlook-tasks-with.html' title='Synchronize your Outlook tasks with iPhone'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-5902064068341805279</id><published>2011-08-15T06:15:00.000-07:00</published><updated>2011-08-15T06:33:08.818-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Linq2sql notSupportedException ArrayLength Linq &quot;Entity Framework&quot;"/><title type='text'>Linq2EF pitfall: Using Length property causes System.NotSupportedException</title><content type='html'>&lt;h3&gt;ArrayLength is not supported in LINQ to Entities&lt;/h3&gt;I spent the last half of previous &lt;a href=&quot;http://www.youtube.com/watch?v=m3qlOsETQug&quot;&gt;friday&lt;/a&gt; banging my head against the wall over a System.NotSupportedException being thrown by Entity Framework 4.0. Now this might be related to the very fact that it was friday and my mind had already started drifting &lt;a href=&quot;http://data.nilzorblog.com/linq2ef/german-beer.jpg&quot;&gt;elsewhere&lt;/a&gt;, but I wasn&#39;t even close to finding the source of the problem. The exception messages sounded &quot;The LINQ expression node type &#39;ArrayLength&#39; is not supported in LINQ to Entities&quot;. When I saw &#39;ArrayLength&#39; mentioned there, and stepping through the code in debug mode seeing that it failed in the foreach statement, I assumed the query went OK but Entity Framework was unable to traverse the result set. This was wrong.&lt;br /&gt;
&lt;p&gt;&lt;b&gt;You cannot use the .Length property of a VARBINARY field in the where clause of an Entity Framework query.&lt;a style=&quot;vertical-align: super; font-size:80%&quot; href=&quot;#note1&quot;&gt;1)&lt;/A&gt;&lt;/b&gt;&lt;p&gt;Now this may not come as a surprise to you, unless you&#39;ve used Linq2SQL. You can there.&lt;br /&gt;
&lt;p&gt;This problem is solved by rewriting the Length check to use the EF static method SqlFunctions.DataLength instead. This will result in EF producing a TSQL statement where the TSQL function DataLength is used on the property in question. This is incidentally what Linq2SQL does behind the scenes as well, without having to be told explicitlty (I found out that by using &lt;a href=&quot;http://www.linqpad.net/&quot;&gt;LinqPad&lt;/a&gt;).&lt;br /&gt;
 &lt;br /&gt;
&lt;p&gt;&lt;a name=&quot;#note1&quot;&gt;1)&lt;/a&gt;&lt;i&gt; This probably goes for the select clause as well, and for all fields having an intrinsic lenght/size property, but this is what I have tested in specific.&lt;/i&gt;&lt;br /&gt;
&lt;h3&gt;A small example - the wrong way&lt;/h3&gt;&lt;pre class=&quot;brush:csharp&quot;&gt;                var results = db.Customers.Where(p =&gt; p.PicutereBlob.Length &gt; 0);
				foreach (var customer in results) { /* Do something */ }
&lt;/pre&gt;Now the exception occurs on line 2 - one of the reasons for my confusion last friday. But of course, that&#39;s how Linq and Entity Framework operates.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;A small example - the right way&lt;/h3&gt;&lt;pre class=&quot;brush:csharp&quot;&gt;                var results = db.Customers.Where(p =&gt; SqlFunctions.DataLength(p.PicutereBlob) &gt; 0);
&lt;/pre&gt;&lt;p&gt;...or in plain Linq syntax:&lt;/p&gt;&lt;pre class=&quot;brush:csharp&quot;&gt;from p in Customers
SqlFunctions.DataLength(p.PicutereBlob) &gt; 0
select p
&lt;/pre&gt;&lt;br /&gt;
&lt;h3&gt;Resulting SQL query:&lt;/h3&gt;&lt;pre class=&quot;brush:sql&quot;&gt;SELECT 
[Extent1].[PictureBlob] AS [PictureBlob], 
FROM [dbo].[Customers] AS [Extent1]
WHERE ( CAST(DATALENGTH([Extent1].[PictureBlob]) AS int)) &gt; 0
&lt;/pre&gt;This will be the statement given that PictureBlob is the only field in the table Customers. &lt;br /&gt;
&lt;p&gt;By the way, This output is semi-directly copy-pasted from the console output while using the brilliant library provided by Jaroslaw Kowalski at &lt;a href=&quot;http://blogs.msdn.com/b/jkowalski/archive/2009/06/11/tracing-and-caching-in-entity-framework-available-on-msdn-code-gallery.aspx&quot;&gt;his MSDN blog&lt;/a&gt;. This gives you the power to monitor all generated SQL queries from the client. A feature which  again, Linq2SQL has by default. This in turn leads to the discussion of why we use Entity Framework in the first place, but I&#39;m not going to &lt;a href=&quot;http://www.hackification.com/2008/12/03/linq-to-entities-the-blackberry-storm-of-orms/&quot;&gt;delve into that hornet nest&lt;/A&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/5902064068341805279/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2011/08/linq2ef-pitfall-using-length-property.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/5902064068341805279'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/5902064068341805279'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2011/08/linq2ef-pitfall-using-length-property.html' title='Linq2EF pitfall: Using Length property causes System.NotSupportedException'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-1153653929380028422</id><published>2011-07-11T07:13:00.000-07:00</published><updated>2011-07-11T07:14:54.488-07:00</updated><title type='text'>Income from paid vs ad-based app</title><content type='html'>When I published my last post, &lt;a href=&quot;http://www.nilzorblog.com/2011/01/android-vs-wp7-for-developers-case.html&quot;&gt;Android vs WP7 - A case study&lt;/A&gt;, I said I had plans to release a free, ad-based version of the app for Android to compare income from ads to income from sales. What&#39;s said is done and I hereby present you with the magic numbers.&lt;br /&gt;
&lt;p&gt;&lt;br /&gt;
&lt;table border=&quot;1&quot;&gt;&lt;tr&gt;&lt;th&gt;Application&lt;th&gt;Downloads&lt;th&gt;Earnings&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;Android, Free (Ads)&lt;td&gt;356&lt;td&gt;$1.75&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;Android, Paid ($1)&lt;td&gt;50&lt;td&gt;$43.11&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;WP7, Paid ($1)&lt;td&gt;75&lt;td&gt;$52.50&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;This blog (Ads)&lt;td&gt;N/A&lt;td&gt;$42.90&lt;br /&gt;
&lt;/table&gt;&lt;p&gt;It should be noted that the ad-based Android app has been on the market a good two months less than the other products in the table. It was released some time in March 2011 (exact date not noted) and the results are collected today, July 11th. &lt;br /&gt;
&lt;p&gt;As you can see, the &quot;income&quot; from the ads from the free version of Flags and Capital Quiz is ridiculously low, even if we compensate for the missing two or three months of market time. Although the volume of the sample data in this &quot;analysis&quot; is far from big enough to draw any absolute conclusions, I think it gives some interesting indications. I for one am not going put all my eggs in the basket of ad-based apps for the Android platform. &lt;br /&gt;
&lt;p&gt;As a fun fact I included the earnings I&#39;ve had for ads on this page (Google Adsense) in the same period of time. I guess one can&#39;t conclude that blogging is more lucrative than writing phone apps based on this, but well...&lt;br /&gt;
&lt;p&gt;When this is said, a interesting new feature has been introduced to the Android platform since I last wrote. Well a lot of interesting new features have been introduced actually, but the one of interest in this context is the ability to exexute &lt;a href=&quot;http://developer.android.com/guide/market/billing/billing_overview.html&quot;&gt;in-app billing&lt;/A&gt; on the platform. This basically gives us the same possibilies as the Trial mode flag on the Windows Phone 7 platform. It just takes a couple of hundred more lines of code ;-) &lt;br /&gt;
&lt;p&gt;Still I&#39;m quite interested in seeing the development of the use of in-app billing in the developer community. Because of the quite crappy income genereated from ads, I&#39;d expect more developers to go for the Trial/Full version licensing model in the time to come. I know a great deal already are, by publishing two separate apps, but I think it will be even more popular with the new model.&lt;br /&gt;
&lt;p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/1153653929380028422/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2011/07/income-from-paid-vs-ad-based-app.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/1153653929380028422'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/1153653929380028422'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2011/07/income-from-paid-vs-ad-based-app.html' title='Income from paid vs ad-based app'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8661585878226033328.post-1828831124687128344</id><published>2011-01-06T11:28:00.000-08:00</published><updated>2011-01-12T11:25:57.233-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="&quot;windows phone 7&quot;"/><category scheme="http://www.blogger.com/atom/ns#" term="android"/><category scheme="http://www.blogger.com/atom/ns#" term="wp7"/><title type='text'>Android vs WP7 for developers - a case study</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;I started my mobile apps &quot;development career&quot; last year by publishing a couple of tools for the Windows Mobile 6.5 platform. I quickly grew fond of the whole apps concept - low threshold for getting started and small programs meaning short projects time-wise. Also the platform took care of the distribution and monetary transactions for me, so that I could care about the thing I find most fun - coding.&lt;br /&gt;
&lt;p&gt;It didn&#39;t take very long until I realized I had to start thinking about other platforms, though. The Windows Mobile 6.x platform (WM6.x for short) was already lagging behind Apple and Google user experience-wise, and the nail in the coffin came when Microsoft announced Windows Phone 7. Everyone who&#39;ve done their research know that the Windows Mobile 6.x platform is as different to Windows Phone 7 as Android is to iOS, so although I was already into Microsoft technology, I knew the choice for my next mobile operating system was anything but given. I had already ruled out Apple iOS for several reasons not relevant here, so my choice was between the rising star of Android from Google, and Microsoft&#39;s new undertaking in the cell phone world - Windows Phone 7 (WP7). &lt;br /&gt;
&lt;p&gt;Microsoft seemed very serious about their new venture. High-ranking Microsoft-guys were preaching the awesomeness of the new platform on conventions and in media all over the world. It seemed like they put a lot of resources into developing the framework and the IDE. At the same time the developers on the WM6.x like me, were given extra attention and information and after a while even offered to get a physical WP7 phone before the official release. It seemed like the path of least resistance to move over to WP7, even though I had to learn Silverlight, but at the same time my friend had bought a HTC Hero phone. Which I found quite cool.&lt;br /&gt;
&lt;p&gt;The Android platform, which HTC seemed to embrace here in Scandinavia, was quickly growing in popularity. iPhone had been the sole market leader for a couple of years and I think the public wanted something new and fresh. Android could seem to be exactly that. They had the sleek look and feel of the iPhone, while taking the technology a step further, which entices us geeks. I was beginning to suspect that this over time could be the new market leader or at least compete with the iPhone. I had done a bit of Java programming at the University, so I wasn&#39;t afraid to try that again, although I knew I had to read up on the framework.&lt;br /&gt;
&lt;p&gt;The technology wasn&#39;t a big factor in the decision I had to take. First and foremost I wanted to make money. Most money with least effort - that was basically my goal (isn&#39;t everyone&#39;s?). Technology is of course a factor when it comes to effort, but most important was which phone was most attractive to the public, hence giving me the largest market. This was of course not possible to say when WP7 wasn&#39;t even in the stores yet. I could only assume that Android would have the market lead for at least half a year after the launch of WP7, if not longer (or forever). But money wasn&#39;t all - it needs to be fun as well. I&#39;m doing this on my spare time, and if it&#39;s not fun, I won&#39;t do it. Could WP7 make up for the lack of market share with the fun factor in the development process?&lt;br /&gt;
&lt;p&gt;This leads me to the topic of this blog. I decided to do a test. I mean, you can&#39;t know which chocolate tastes best before you&#39;ve tried both, right? (You may quote me on that). For the test to be fair, I decided to make the exact same application on both platforms, and see where it got me. The application had to be simple so that I could do it in a short period of time, but not so simple that it didn&#39;t put the framework and IDE to a test. I was going to note down my experiences during the process and write about the result here. I decided this some time in September, and the 20th of November I released the app on the second platform, completing my project.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;The App&lt;/h2&gt;I decided to go for a simple game I had seen the likes of at the iPhone platform and also on Android: A flag and country quiz. It would require some graphics, some business logic and probably some storage. Enough for a basic test, but far from a thorough. I would not be leveraging any of the more advanced hardware or even a network connection or sound device, but I wanted to be done in a couple of months - and I had to learn not one, but two new frameworks. But most important - the complexity of the programming (or lack of it) is not directly relevant to sales numbers - the prime factor I wanted to compare. This simple game should suffice, was my conclusion.&lt;br /&gt;
&lt;p&gt;A quick overview of the game, which is called &quot;Flags and Captital Quiz&quot; on both platform:&lt;br /&gt;
&lt;p&gt;There are five game modes:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Guess country name from the picture of a flag&lt;br /&gt;
&lt;li&gt;Guess the flag from the name of a country&lt;br /&gt;
&lt;li&gt;Guess the capital from the country name&lt;br /&gt;
&lt;li&gt;Guess the country name from the capital&lt;br /&gt;
&lt;li&gt;A mixed mode which alternates randomly of the four above&lt;br /&gt;
&lt;/ul&gt;All five modes each give four alternatives for the answer, so the user simply picks one of them by clicking on it. A couple of screenshots: &lt;p&gt;&lt;table&gt;&lt;tr&gt;   &lt;td&gt;&lt;img width=&quot;150&quot; src=&quot;http://data.nilzorblog.com/android-wp7/ss1.png&quot;&gt;&lt;/td&gt;   &lt;td&gt;&lt;img width=&quot;150&quot; src=&quot;http://data.nilzorblog.com/android-wp7/ss2.png&quot;&gt;&lt;/td&gt;   &lt;td&gt;&lt;img width=&quot;150&quot; src=&quot;http://data.nilzorblog.com/android-wp7/ss3.png&quot;&gt;&lt;/td&gt;  &lt;/tr&gt;
&lt;/table&gt;&lt;p&gt;&lt;h2&gt;The IDEs&lt;/h2&gt;&lt;p&gt;This chapter describes the differences in the extended IDEs, meaning both the editor, compiler, debugger and emulators.&lt;/p&gt;&lt;h3&gt;Android&lt;/h3&gt;For those of you who&#39;ve never developed in Java, the preferred IDE is called Eclipse and can be downloaded for free at &lt;a href=&quot;http://www.eclipse.org&quot;&gt;www.eclipse.org&lt;/a&gt;. In addition you&#39;ll need the &lt;a href=&quot;http://developer.android.com/sdk/index.html&quot;&gt;Android SDK&lt;/A&gt; from Google which acts as a plug-in in Eclipse. It will also provide you with the Android emulator to test your software without a physical device. &lt;p&gt;The installation went smooth, nothing to complain about here. Eclipse in itself is also a pretty smooth IDE. It has some semi advanced features that Visual Studio didn&#39;t have until the 2010-version, which is quite impressive. I&#39;m thinking of things like code inspection reporting instantly of non-used variables, syntax errors and more. It also have some refactoring features but I haven&#39;t delved into these. The debugger has all the functions you&#39;d expect, although I do have some complaints on usability here. I find inspecting variables and object hierarchies run-time easier in VS2010, but it might be that I haven&#39;t understood properly how to use it yet. But all in all the feel of Eclipse is good. It&#39;s fast and feels light-weight even though it isn&#39;t.  &lt;p&gt;Where Eclipse comes short compared to Visual Studio is in designing UI. There simply is no designer in Eclipse. You need to rely on your XML skills and ability to visualize XML as UI components. Or use a tool like &lt;a href=&quot;http://www.droiddraw.org/&quot;&gt;DroidDraw&lt;/a&gt;. But even the combination of Eclipse + DroidDraw falls way short of the design capabilities of VS2010 working with Silverlight projects.  &lt;h3&gt;Visual Studio 2010&lt;/h3&gt;If I would describe Visual Studio 2010 in one word, I would say &lt;i&gt;huge&lt;/i&gt;. It&#39;s huge in all aspects: Installation process, disk footprint, runtime footprint, features, everything. But as long as you have a machine capable of hauling it, it&#39;s a dream to work with. I just had to make space for the 3 GB of disk requirement on C: before I could start (You do need 3 GB free space on C: even if you chose to install it on D:, meaning my tight fragmentation strategy of the C-partition failed). &lt;p&gt;Visual Studio have basically all the same core features as Eclipse, so the coding experience itself is not much different. There is one aspect I found slightly better in the Microsoft world, and that&#39;s the phone emulator. It&#39;s better integrated in the IDE for natural reasons (Microsoft produce both the IDE and the emulator), and this results in a lightning fast and stable launch process. The first boot of the emulator takes time, but after it is up an running, I literally only wait two seconds from I&#39;ve made a code change and hit F5 (debug), until it&#39;s up and running in the emulator. Not once did I face any problems running the app, while with the Android emulator I experienced increasing problems towards the end of the project with getting Eclipse to connect to the Android debugger. Frequent restarts had to be done of both Eclipse and the debugger. &lt;p&gt;Ignoring the slight problems I had with connecting the debugger to the Android emulator, the major difference between the IDEs is the designer (or the lack of in the case of Eclipse). Hard-core coders who frown upon using visual tools to do the design have no respect with me. I use whatever tool gets the job done quickest and with best result. If drag-and-drop creates code 10 times faster than I could write it, no matter how much intellisense support there is in the IDE, I use drag-and-drop. But more important than coding speed itself is how much easier it is to design. Our brain (or the right hand side of it at least), responds much quicker to concrete visual modelling than abstract representation in the form of XML or XAML. This is where the real time-saver is. You instantly see why the three Images underneath the ListBox with four icons is a good or bad idea - no need to compile and run first. &lt;/p&gt;&lt;h3&gt;Summary&lt;/h3&gt;&lt;table class=&quot;grid-1&quot; border=&quot;0&quot; width=&quot;500&quot;&gt;&lt;tr&gt;&lt;th align=left&gt;Eclipse&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Visual Studio 2010&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=top&gt;&lt;a href=&quot;http://data.nilzorblog.com/android-wp7/ide_eclipse.jpg&quot;&gt;&lt;img width=&quot;200&quot; src=&quot;http://data.nilzorblog.com/android-wp7/ide_eclipse.jpg&quot;&gt;&lt;/a&gt;&lt;div class=&quot;caption&quot;&gt;Instant code analysis feedback is good in Eclipse&lt;/div&gt;&lt;/td&gt;&lt;td valign=top&gt;&lt;a href=&quot;http://data.nilzorblog.com/android-wp7/ide_vs2010.jpg&quot;&gt;&lt;img width=&quot;200&quot; src=&quot;http://data.nilzorblog.com/android-wp7/ide_vs2010.jpg&quot;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class=&quot;caption&quot;&gt;Changes you do in the left view instantly results in XAML code change in the rigght, and vice versa.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;div class=&quot;plus&quot;&gt;Lightweight / fast / responsive&lt;/div&gt;&lt;/td&gt;&lt;td&gt;&lt;div class=&quot;plus&quot;&gt;Quick and stable emulator&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;div class=&quot;plus&quot;&gt;Free&lt;/div&gt;&lt;/td&gt;&lt;td&gt;&lt;div class=&quot;plus&quot;&gt;Great visual designer&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;div class=&quot;minus&quot;&gt;No visual designer&lt;/div&gt;&lt;/td&gt;&lt;td&gt;&lt;div class=&quot;minus&quot;&gt;Huge footprint&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;p&gt;&lt;i&gt;Update 7th Jan: I was noted that the development tools for WP7 are actually also free - the Visual Studio Express and Blend for Windows Phone 7 are free of charge. They can be installed alongside any other preexisting Visual Studio installation.&lt;/i&gt; &lt;p&gt;&lt;table width=&quot;500&quot; class=&quot;grid-1&quot;&gt;&lt;tr&gt;&lt;th align=left&gt;The Android emulator&lt;/th&gt;&lt;th align=left&gt;The WP7 emulator&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;  &lt;td valign=top&gt;&lt;a href=&quot;http://data.nilzorblog.com/android-wp7/emu_android.jpg&quot;&gt;&lt;img height=&quot;170&quot; src=&quot;http://data.nilzorblog.com/android-wp7/emu_android.jpg&quot;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;caption&quot;&gt;Boots fast, launches programs fast. Solid. Had some problems connecting to the debugger from time to time, but might be a configuration-problem.&lt;/div&gt;&lt;/td&gt;   &lt;td valign=top&gt;&lt;a href=&quot;http://data.nilzorblog.com/android-wp7/emu_wp7.jpg&quot;&gt;&lt;img height=&quot;170&quot; src=&quot;http://data.nilzorblog.com/android-wp7/emu_wp7.jpg&quot;&gt;&lt;/A&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;caption&quot;&gt;Also solid. The emulators are really not what make the difference.&lt;/div&gt;&lt;/td&gt;&lt;/td&gt;   &lt;/tr&gt;
&lt;/table&gt;&lt;/P&gt;&lt;h2&gt;The development process and the APIs&lt;/h2&gt;In this chapter I will describe the development process session by session on the two platforms, emphasizing the events that stand out as positive or negative. Finally I will summarize what I find good and bad about the frameworks (APIs) that is the Android SDK and the WP7 / Silverlight framework.  &lt;ul&gt;&lt;li&gt;For Android I used the Android 1.6 SDK &lt;br /&gt;
&lt;li&gt;Windows Phone 7: Standard WP7 project based on .NET 4.0&lt;br /&gt;
&lt;/ul&gt;For those of you who are confused about the Windows Phone 7 SDK stack, this is the gist of it &lt;ul&gt;&lt;li&gt;C# is the programming language&lt;br /&gt;
&lt;li&gt;.NET 4.0 is the core libraries (non-UI-functions)&lt;br /&gt;
&lt;li&gt;Silverlight is the SDK which enables rich UI for web, Windows and WP7, but:&lt;br /&gt;
&lt;li&gt;The Windows Phone 7 SDK is a subset of Silverlight and .NET 4.0 - not all functions and UI elements from Silverlight 4 or .NET 4.0 exists on WP7.&lt;br /&gt;
&lt;/ul&gt;&lt;h3&gt;Android&lt;/h3&gt;&lt;table class=&quot;grid-1&quot;&gt;&lt;tr&gt;&lt;th&gt;#&lt;/th&gt;&lt;th width=&quot;80&quot;&gt;Time spent&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;What&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;1&lt;/td&gt;   &lt;td&gt;1h 30min&lt;/td&gt;   &lt;td&gt;Collected and organized data: Flags, capitals and countries from the &lt;a href=&quot;https://www.cia.gov/library/publications/the-world-factbook/&quot;&gt;CIA World Factbook&lt;/a&gt;&lt;/td&gt;  &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;2&lt;/td&gt;   &lt;td&gt;3h 20min&lt;/td&gt;   &lt;td&gt;Read basics on Android development, learning Eclipse better&lt;br /&gt;
&lt;div class=&quot;plus&quot;&gt;Google have &lt;a href=&quot;http://developer.android.com/guide/topics/fundamentals.html&quot;&gt;documented Android&lt;/a&gt; well. Well structured and written.&lt;/div&gt;&lt;/td&gt;  &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;3&lt;/td&gt;   &lt;td&gt;4h&lt;/td&gt;   &lt;td&gt;Worked on designing and implementing code for my first pages (Activities). Spent time both in XML and in Java code. Wasted a lot of time trying to figure out how to pass parameters with intents. Ended up using global variables instead.&lt;br /&gt;
&lt;div class=&quot;minus&quot;&gt;Soon got tired of XML-juggling. Little IDE-help here.&lt;/div&gt;&lt;/td&gt;  &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;4&lt;/td&gt;   &lt;td&gt;2h 30min&lt;/td&gt;   &lt;td&gt;Spent most time trying to figure out how to make buttons turn red and green after an answer had been made. Tried three approaches before finally finding the right answer on the net (Hint: Drawable.setColorFilter()).&lt;/td&gt;  &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;5&lt;/td&gt;   &lt;td&gt;2h 30min&lt;/td&gt;   &lt;td&gt;Working on business logic. Three out of five quiz modes complete.&lt;/td&gt;  &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;6&lt;/td&gt;   &lt;td&gt;1h&lt;/td&gt;   &lt;td&gt;Mixed mode implemented.&lt;/td&gt;  &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;7&lt;/td&gt;   &lt;td&gt;1h 30min&lt;/td&gt;   &lt;td&gt;Settings screen (activity) implemented. Functionality for saving/loading said settings still remain.&lt;/td&gt;  &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;8&lt;/td&gt;   &lt;td&gt;4h&lt;/td&gt;   &lt;td&gt;Implemented practice and score mode. Textual &quot;fun&quot; feedback on the results. Half done with high score list functionality&lt;br /&gt;
&lt;div class=&quot;minus&quot;&gt;Getting problems attaching to the debugger more often. Restarts requried.&lt;/div&gt;&lt;div class=&quot;minus&quot;&gt;Annoyed by the fact that hitting F5 when an XML file is in focus, the app is not launched, but instead Eclipse tries to launch XML files in a special manner, effectively forcing me to clean the entire project and rebuild. Wasting some time on this.&lt;/div&gt;&lt;/td&gt;  &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;9&lt;/td&gt;   &lt;td&gt;4h&lt;/td&gt;  &lt;td&gt;Spent some time drawing icons. High score list implemented. Icon swapping in high score list. The project is starting to show signs of a lot of copy-pasted code in the activities. Probably because of bad design - for instance, &lt;a href=&quot;http://developer.android.com/guide/topics/ui/custom-components.html&quot;&gt;Custom components&lt;/a&gt; is a conecpt I did not bother to read up on.&lt;/td&gt;  &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;10&lt;/td&gt;   &lt;td&gt;3h 30min&lt;/td&gt;   &lt;td&gt;Last mode, flag from country, implementation beugn. Most demanding activity XML. &lt;/td&gt;  &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;11&lt;/td&gt;   &lt;td&gt;3h&lt;/td&gt;   &lt;td&gt;Completed flag from country mode. Implemented saving and loading of settings and high scores with JSON serialization.&lt;br /&gt;
&lt;div class=&quot;plus&quot;&gt;Saving and loading user settings is well supported and easy to use in the Android framework&lt;/div&gt;&lt;div class=&quot;minus&quot;&gt;Object serialization in the Java world could have been easier (used for high score object hierarchy). I used standard org.Json-functions. There is a library called &lt;a href=&quot;http://code.google.com/p/google-gson/&quot;&gt;Gson&lt;/a&gt; that probably could have made my code prettier, but at this point I did not want to introduce additional third-party libraries in my project.&lt;/div&gt;&lt;/td&gt;  &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;12&lt;/td&gt;   &lt;td&gt;1h 30min&lt;/td&gt;   &lt;td&gt;Completion of diverse functionality&lt;/td&gt;    &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;13&lt;/td&gt;   &lt;td&gt;5h&lt;/td&gt;   &lt;td&gt;Some bug-fixing. Fixed memory leak (image data was not freed). Created application icon. Published at Saturday 21th of October..&lt;br /&gt;
&lt;div class=&quot;plus&quot;&gt;The publishing process went smooth and was straight forward.&lt;/div&gt;&lt;/td&gt;  &lt;/tr&gt;
&lt;/table&gt;&lt;h3&gt;WP7&lt;/h3&gt;&lt;table class=&quot;grid-1&quot;&gt;&lt;tr&gt;&lt;th&gt;#&lt;/th&gt;&lt;th width=&quot;80&quot;&gt;Time spent&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;What&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;1&lt;/td&gt;   &lt;td&gt;1h 30min&lt;/td&gt;   &lt;td&gt;Started designing the pages (Activities on Android).&lt;br /&gt;
&lt;div class=&quot;minus&quot;&gt;Finding the &lt;a href=&quot;http://create.msdn.com/en-us/education/documentation&quot;&gt;WP7 documentation pages&lt;/a&gt; slightly harder to navigate than the one for Android as I try to read up on Silverlight design concepts.&lt;/div&gt;&lt;/td&gt;  &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;2&lt;/td&gt;   &lt;td&gt;1h&lt;/td&gt;   &lt;td&gt;Trying to apply databindning.&lt;br /&gt;
&lt;div class=&quot;minus&quot;&gt;Having worked with databinding on WinForms, doing the same on Silverlight is a step back. You suddenly need to write XAML and learn meta-syntax in quotation marks that I still haven&#39;t quite figured out. Copy-paste is your friend.&lt;/div&gt;&lt;/td&gt;  &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;3&lt;/td&gt;   &lt;td&gt;3h 30min&lt;/td&gt;   &lt;td&gt;Button colouring, flag animation, practice mode and score mode. Note: I did not implement any animation on the Android version, so I&#39;m slightly deviating from the &quot;same app, different platform&quot; concept of my review here, but I couldn&#39;t help myself but leverage the animation capabilities of Silverlight.&lt;br /&gt;
&lt;div class=&quot;plus&quot;&gt;The animation features in Silverlight are &lt;i&gt;awesome&lt;/i&gt;. Takes a bit of learning, though.&lt;/div&gt;&lt;/td&gt;  &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;4&lt;/td&gt;   &lt;td&gt;1h 30 min&lt;/td&gt;   &lt;td&gt;High score logic implemented (no storage)&lt;/td&gt;  &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;5&lt;/td&gt;   &lt;td&gt;1h 30min&lt;/td&gt;   &lt;td&gt;More work on the high scores screen. Refactoring pages a bit - creating UserControls for the image buttons used in the high scores view and a control for the score bar in the quiz pages&lt;/td&gt;  &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;6&lt;/td&gt;   &lt;td&gt;3h&lt;/td&gt;   &lt;td&gt;Applcation icon included in project. Struggled a bit with getting it to display properly. Turned out it had to have the build action property set to &quot;Content&quot;. Save and load of high scores. Support for tombstoning (when app sleeps in background) implemented.&lt;br /&gt;
&lt;div class=&quot;minus&quot;&gt;The tombstoning concept was a pain in the ass. No such thing on Android, but this is a consequence of the non-multitasking nature of WP7, I guess&lt;/div&gt;&lt;div class=&quot;plus&quot;&gt;Object serialization is fortunately a breeze in .NET, which helps when saving object state when tombstoning.&lt;/div&gt;&lt;/td&gt;  &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;8&lt;/td&gt;   &lt;td&gt;5h&lt;/td&gt;   &lt;td&gt;Refactored all quiz mode pages to user controls. Now mixed mode was implemented in half an hour. Flag from country mode implemented&lt;br /&gt;
&lt;div class=&quot;plus&quot;&gt;The App Manifest is auto-generated as opposed to on Android. Meaning the compiler among other things auto detects what kind of hardware resource your application will be utilizing.&lt;/div&gt;&lt;div class=&quot;minus&quot;&gt;VS2010/XAML editing lacks good support for refactor-renaming things like animation timeline names&lt;/div&gt;&lt;/td&gt;     &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;9&lt;/td&gt;   &lt;td&gt;1h&lt;/td&gt;   &lt;td&gt;Improved some animation (half hour) and added support for trial mode, which is a feature unique to the Microsoft Marketplace. You may actually provide the user with an option to try before they buy the software, all which is controlled with a single boolean in your code. Simple and effective!&lt;br /&gt;
&lt;div class=&quot;plus&quot;&gt;The IsTrial boolean is brilliant&lt;/div&gt;&lt;/td&gt;  &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;10&lt;/td&gt;   &lt;td&gt;0h 30min&lt;/td&gt;   &lt;td&gt;Submitted at the 20th of November. Read more about submission process below&lt;/td&gt;  &lt;/tr&gt;
&lt;/table&gt;&lt;h3&gt;Summary&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Total time on Android: 35 hours 30 minutes&lt;br /&gt;
&lt;li&gt;Total time on WP7: 18 hours&lt;br /&gt;
&lt;/ul&gt;&lt;p&gt;&lt;i&gt;&lt;b&gt;These numbers lie&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;&lt;p&gt;There are several reasons the WP7-development went faster. &lt;ul&gt;&lt;li&gt;I had the resource files ready (flags and data xml&#39;s)&lt;br /&gt;
&lt;li&gt;I could reuse architectural principles i used in the Android project (brain time)&lt;br /&gt;
&lt;li&gt;I reused actual code by copy-pasting and changing &quot;boolean&quot; into &quot;bool&quot; etc. (code time)&lt;br /&gt;
&lt;/ul&gt;All in all I think this is much closer to a draw time-wise than what my numbers show. I think the main difference is not development time, but what I got out of that time. The WP7-version is simply cooler because of the animation effects I so easily could add.  &lt;p&gt;In any case, I did a breakdown on the numbers, dividing time spent into five categories: Gathering and prepare resources (images, dat), Studying (googling and reading), Coding (actual C# or Java work), UI-develpoment (XML/XAML) and publishing. You do need to take these numbers with a grain of salt. It&#39;s very difficult to say exact how much time I spent on each activity, but I think it gives an indication. Instead of presenting the numbers in a table, I made these beautiful pie charts: &lt;p&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Android&lt;/th&gt;&lt;th style=&quot;padding-left:20px&quot;&gt;WP7&lt;/th&gt;&lt;th&gt;&lt;/tr&gt;&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;&lt;img width=&quot;200&quot; src=&quot;http://data.nilzorblog.com/android-wp7/pie-android.png&quot;&gt;&lt;/td&gt;&lt;td style=&quot;padding-left:20px&quot; &gt;&lt;img width=&quot;200&quot; src=&quot;http://data.nilzorblog.com/android-wp7/pie-wp7.png&quot;&gt;&lt;/td&gt;&lt;td&gt;&lt;img src=&quot;http://data.nilzorblog.com/android-wp7/legend.png&quot;&gt;&lt;/tD&gt;&lt;/tr&gt;&lt;br /&gt;
&lt;/table&gt;&lt;/p&gt;&lt;p&gt;The most interesting fact I get out of these pie charts is the difference in time spent doing &quot;UI&quot;. Now this may be a question of definition, but I did spend proprtionally more time working in the designer and with XAML than with code on WP7 compared to Android. Maybe it&#39;s because Silverlight more fun, so I took time to work on things like animation and stuff? Maybe it&#39;s because I knew better what to code, so that the business logic was done faster the second time around? Probably a combination.   &lt;br /&gt;
&lt;/p&gt;&lt;h2&gt;The submission process&lt;/h2&gt;&lt;p&gt;The sumbission process are pretty similar. I suppose Google and Microsoft have learned from each other and copied some ideas. The basic info you need to fill out and upload on both places are:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Name&lt;br /&gt;
&lt;li&gt;Description&lt;br /&gt;
&lt;li&gt;Binaries&lt;br /&gt;
&lt;li&gt;Icon, screenshots and artwork&lt;br /&gt;
&lt;li&gt;Pricing details&lt;br /&gt;
&lt;/ul&gt;There are some slight differences.  &lt;ul&gt;&lt;li&gt;The android platform requires you to enter a content rating (Teen/Mature, etc)&lt;br /&gt;
&lt;li&gt;The WP Marketplace allows you to price the product differently in different countries.&lt;br /&gt;
&lt;li&gt;Android allows advanced copy protection with a licensing server. Takes some implementing. Unsure where WP7 stands here.&lt;br /&gt;
&lt;li&gt;WP7 allows support for trial mode&lt;br /&gt;
&lt;/ul&gt;The last bullet point here is a big plus for the Windows Phone Marketplace, if you ask me. This allows users to download a single binary that acts as a trial until the user purchases the product. It is then unlocked by setting a bool IsTrial=true, which you must have code for. This way, publishers don&#39;t have to upload two separate versions, which I see is very common on the iPhones. On the Android platform though, I see the norm is more to publish ad-based applications. But maybe it would be different with the Trial-option there as well.  &lt;/p&gt;All in all, both platforms allow a good user interface for uploading applications. When you have your material ready, the publishing itself is done in half an hour or less. As a side note, for those of you who&#39;ve worked with Windows Marketplace for Windows Mobile 6.5 and earlier, you&#39;ll see that the new interface is a &lt;i&gt;huge&lt;/i&gt; step up from that old monster of a form. &lt;p&gt;&lt;table class=&quot;grid-1&quot;&gt;&lt;tr&gt;&lt;td valign=&quot;top&quot; width=&quot;200&quot;&gt;&lt;a href=&quot;http://data.nilzorblog.com/android-wp7/submit_android.png&quot;&gt;&lt;img height=&quot;170&quot; class=&quot;imgborder&quot; src=&quot;http://data.nilzorblog.com/android-wp7/submit_android.png&quot;&gt;&lt;/a&gt; &lt;br /&gt;
&lt;div class=&quot;caption&quot;&gt;About half of the Android app submission form&lt;/div&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;200&quot;&gt;&lt;a href=&quot;http://data.nilzorblog.com/android-wp7/submit_wp7.png&quot;&gt;&lt;img style=&quot;border: 1px gray solid&quot; height=&quot;170&quot; src=&quot;http://data.nilzorblog.com/android-wp7/submit_wp7.png&quot;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class=&quot;caption&quot;&gt;Page one of five in the WP7 submission process&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;







&lt;/table&gt;&lt;p&gt;&lt;h2&gt;The report interfaces&lt;/h2&gt;When your app is published, it&#39;s time to kick back and watch the money flow in. Also here, the interfaces are good on both platforms, but I&#39;d give Google a minor win. Google reports every single purchase with full name, date and country of the buyer, while Microsoft settles for a summary per country. Microsoft gives you a sleek graph, though - that&#39;s cool. Another thing that is a big plus for Google is the error report interface. You can actually see each single exception that occur runtime on any single phone in the world - with full stacktrace. There is no such thing at Microsoft&#39;s platform. &lt;p&gt;Since pictures says more than a thousand words:

&lt;p&gt;&lt;h3&gt;Android Market Publish Site&lt;/h3&gt;&lt;table class=&quot;grid-1&quot;&gt;&lt;tr&gt;&lt;td valign=&quot;bottom&quot;&gt;&lt;a href=&quot;http://data.nilzorblog.com/android-wp7/reports_android_mainpage.png&quot;&gt;&lt;img width=&quot;180&quot; class=&quot;imgborder&quot; src=&quot;http://data.nilzorblog.com/android-wp7/reports_android_mainpage.png&quot;&gt;&lt;/A&gt;&lt;/td&gt;   &lt;td valign=&quot;bottom&quot;&gt;&lt;a href=&quot;http://data.nilzorblog.com/android-wp7/reports_android_nonames.png&quot;&gt;&lt;img width=&quot;180&quot; class=&quot;imgborder&quot; src=&quot;http://data.nilzorblog.com/android-wp7/reports_android_nonames.png&quot;&gt;&lt;/A&gt;&lt;/td&gt;   &lt;td valign=&quot;bottom&quot;&gt;&lt;a href=&quot;http://data.nilzorblog.com/android-wp7/reports_android_errors.png&quot;&gt;&lt;img width=&quot;180&quot; class=&quot;imgborder&quot; src=&quot;http://data.nilzorblog.com/android-wp7/reports_android_errors.png&quot;&gt;&lt;/A&gt;&lt;/td&gt;   &lt;td valign=&quot;bottom&quot;&gt;&lt;a href=&quot;http://data.nilzorblog.com/android-wp7/reports_android_nullpointer.png&quot;&gt;&lt;img width=&quot;180&quot; class=&quot;imgborder&quot; src=&quot;http://data.nilzorblog.com/android-wp7/reports_android_nullpointer.png&quot;&gt;&lt;/A&gt;&lt;/td&gt;  &lt;/tr&gt;
&lt;tr&gt;    &lt;td&gt;&lt;div class=&quot;caption&quot;&gt;Android Market main page&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;&lt;div class=&quot;caption&quot;&gt;Detailed Sales Report&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;&lt;div class=&quot;caption&quot;&gt;Android Market Error Report page&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;&lt;div class=&quot;caption&quot;&gt;Android Market Error Details. Luckily I added a bug just so that I could demonstrate this feature for you!&lt;/div&gt;&lt;/td&gt;  &lt;/tr&gt;
&lt;/table&gt;
&lt;h3&gt;Windows Phone App Hub&lt;/h3&gt;&lt;table class=&quot;grid-1&quot;&gt;&lt;tr&gt;&lt;td valign=&quot;bottom&quot;&gt;&lt;a href=&quot;http://data.nilzorblog.com/android-wp7/reports_wp7.png&quot;&gt;&lt;img width=&quot;180&quot; class=&quot;imgborder&quot; src=&quot;http://data.nilzorblog.com/android-wp7/reports_wp7.png&quot;&gt; &lt;/A&gt;&lt;/td&gt;   &lt;td valign=&quot;bottom&quot;&gt;&lt;a href=&quot;http://data.nilzorblog.com/android-wp7/reports_wp7_2.png&quot;&gt;&lt;img width=&quot;180&quot; class=&quot;imgborder&quot; src=&quot;http://data.nilzorblog.com/android-wp7/reports_wp7_2.png&quot;&gt;&lt;/A&gt;&lt;/td&gt;   &lt;td valign=&quot;bottom&quot;&gt;&lt;a href=&quot;http://data.nilzorblog.com/android-wp7/reports_wp7_3.png&quot;&gt;&lt;img width=&quot;180&quot; class=&quot;imgborder&quot; src=&quot;http://data.nilzorblog.com/android-wp7/reports_wp7_3.png&quot;&gt;&lt;/A&gt;&lt;/td&gt;  &lt;/tr&gt;
&lt;tr&gt;    &lt;td&gt;&lt;div class=&quot;caption&quot;&gt;Daily download details&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;&lt;div class=&quot;caption&quot;&gt;Daily cumulative&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;&lt;div class=&quot;caption&quot;&gt;Data summary table per country&lt;/div&gt;&lt;/td&gt;  &lt;/tr&gt;
&lt;/table&gt;&lt;p&gt;&lt;h2&gt;Sales numbers&lt;/h2&gt;Finally some numbers. After each application had been on the market for a month, I gathered the numbered and these are the results:
&lt;table class=&quot;grid-1&quot;&gt;&lt;tr&gt;&lt;th&gt;&amp;nbsp;&lt;/th&gt;&lt;th&gt;Android&lt;/th&gt;&lt;th&gt;WP7&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Trial      &lt;/td&gt;&lt;td align=&quot;right&quot;&gt;N/A&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;125&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Full version&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;15&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;36&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;p&gt;Both were priced at $1.&lt;p&gt;
Now I think there are several reasons why I sold better at the WP7-platform. For one there is less competition there. I could not see any other apps at the time of publishing that had this kind of flag quiz. On Android there were three or four pretty similar. For free. I&#39;m surprised I actually sold any at all. 
&lt;p&gt;&lt;h2&gt;Summary&lt;/h2&gt;So I&#39;m not going to be rich on this application, but it&#39;s been a fun project. Before I leave the sales figures: I have plans to release a new version on Android (and maybe also WP7) that will be ad-based and free instead of priced at $1. I suspect I&#39;ll compete better with the other free application then, but will I make more money? It will be an interesting experiment as well, and I&#39;ll probably post a new blog entry about the results in a couple of months.
&lt;p&gt;But who wins? Where will I go? I do believe it&#39;s slightly more fun to work at the WP7 platform, but the differences are not that big. Not big enough to be decisive alone. I do own a vey cool Android-based Samsung Galaxy S phone now, which is a factor that makes me want to develop for Android. I do have a WP7-device as well (on loan from Microsoft), but I actually think the Android device is slightly cooler to use and play with. 
&lt;p&gt;Then there is the user base, which I talked about in the introduction. The user base for Android is still quite much bigger than for Windows Phone, and that is the factor that makes me pretty sure that my next project will be on an Android device. I reach a greater audience, and that&#39;s always cool both in terms of revenue and feedback. Who want&#39;s to work for weeks in a cellar and when the day comes for publishing, you never hear a word of praise or criticism? So the next project: Android, but the next after that? Who knows - I go where the wind blows.
&lt;p&gt;Dice roll comparison chart:
&lt;table class=&quot;grid-1&quot;&gt;&lt;tr&gt;&lt;th align=left&gt;Aspect&lt;th align=center&gt;Android &amp;nbsp;&amp;nbsp;&lt;th align=center&gt;WP7&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;IDEs&lt;td align=center&gt;4&lt;td align=center&gt;6&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;APIs&lt;td align=center&gt;4&lt;td align=center&gt;5&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;Availability of documentation&lt;td align=center&gt;6&lt;td align=center&gt;5&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;Reporting functionality&lt;td align=center&gt;5&lt;td align=center&gt;4&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;Submission process&lt;td align=center&gt;5&lt;td align=center&gt;5&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;Perceived market potential&lt;td align=center&gt;5&lt;td align=center&gt;4&lt;br /&gt;
&lt;tr&gt;&lt;td&gt;Total&lt;td align=center&gt;29&lt;td  align=center&gt;29&lt;br /&gt;
&lt;/table&gt;&lt;p&gt;It&#39;s a draw! -Everybody is happy and I&#39;m avoiding Microsoft vs Google, Closed vs Open source-debates in the comments - perfect! :-)&lt;br /&gt;
&lt;p&gt;Happy app developing!</content><link rel='replies' type='application/atom+xml' href='http://www.nilzorblog.com/feeds/1828831124687128344/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.nilzorblog.com/2011/01/android-vs-wp7-for-developers-case.html#comment-form' title='63 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/1828831124687128344'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8661585878226033328/posts/default/1828831124687128344'/><link rel='alternate' type='text/html' href='http://www.nilzorblog.com/2011/01/android-vs-wp7-for-developers-case.html' title='Android vs WP7 for developers - a case study'/><author><name>Frode Nilsen</name><uri>http://www.blogger.com/profile/11779675194677466654</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD-shmElDDOKqAcEJpePczlM7IYxSgryjs9ThXkgO4F9z8rGDjaaryqdW7ZweoWT3LnejvbYo77ibOkc7HhhDxhw5COpGcb2XptnSw-QFaw4hTUtwENQets8oKhwAxL3E/s113/frode-nilsen-jan2020-profil.jpg'/></author><thr:total>63</thr:total></entry></feed>