Analyzing PhoneGap for mobile application development

Recently I was looking at how we could leverage our existing HTML5/CSS3/JavaScript code and skills to create a mobile application that we could easily deploy to the various stores, mainly Apple, Google Play and Windows.
A few people suggested PhoneGap. But before we jumped all in into PhoneGap development, I wanted to analyze and make sure it could be the answer to what we were looking for.

I put together this very brief analysis of PhoneGap for mobile application development. Though PhoneGap is open source and is advertised as standardized APIs without requiring native SDKs, for all practical purposes I found there were a lot of caveats.

Pros Cons
Leverages HTML5/Javascript/CSS3 skills of developers Need to pay attention to lack of certain features in mobile browsers e.g. SVG
UIWebView control allows using PhoneGap API irrespective of underlying mobile platform
  • Performance of the app using the UIWebView control is slightly lower than using native code app
  • Look and feel of different controls within the UIWebView control differs among the different platforms
  • Since the UIWebView control loads resources locally, cross domain policy needs to be considered for resources located on server
Testing and debugging using desktop browsers and mobile simulators Different IDEs are required for development for each mobile platform
Can copy HTML/CSS/JS source code files for each platform to different codebases thus effectively sharing code
  • Separate codebases still need to be maintained for each platform build
  • Code is not compiled into native language
For builds, Native installers created using target platform tool chain (native SDKs) or cloud based PhoneGap Build (not free)

 

In detail, for each PhoneGap platform:

  • You can develop Android and HP webOS apps on any of the major desktop operating systems – Windows, Mac OS X, or Linux.
  • You can develop Symbian Web Runtime apps on any OS, but you can only run the simulator from Windows.
  • Developing for BlackBerry is similar – the SDK can be installed on Windows or Mac OS X, but, at the time of writing, the simulator only runs on Windows.
  • The Windows Phone 7 SDK only runs on Ubuntu Linux, versions 10.04 and above. (? Unverified)
  • The iOS SDK requires the latest version, 10.6, of Mac OS X (and, according to the OS X EULA, a Mac computer as well though some people claim to have installed it virtually).

 

In short, with a Windows developer PC, a mobile application can be built for multiple platforms including Windows Phone, Android except iOS.

 

Software Requirements for development using PhoneGap for the 3 major platforms

Dev requirement Windows 8 iOS Android
Hardware Windows PC Mac (Windows PC possible if able to install Mac OS X virtually, YMMV) Windows PC or Mac
Operating system Windows 8 Mac OS X Windows, Mac OS X or Linux
SDK Windows 8 store JS templates iOS 6 SDK
  • JDK
  • Android SDK
  • Android Developer Tools
  • Android Platform
  • Android Platform Tools
Recommended IDE Visual Studio 2012 Express or higher XCode 4.5 or higher Eclipse Classic or Higher

 

Some interesting articles/discussions regarding PhoneGap (not in any particular order)

ELMAH vs Enterprise Library Logging Application Block – a brief comparison

I couldn’t find one single resource where I could easily compare ELMAH with the Enterprise Library Logging application block. Instead, the various features, benefits and design of these two logging frameworks are spread across multiple websites. Hence, I have collated information from these disparate sources hoping that it would bring about a succinct yet meaningful comparison between the two.

Enterprise Library Logging Application Block

The Enterprise Library Logging Application Block simplifies the implementation of common logging functions. You can use the Logging Application Block to write information to a variety of locations:

  • The event log
  • An e-mail message
  • A database
  • A message queue
  • A text file
  • A Windows® Management Instrumentation (WMI) event
  • Custom locations using application block extension points

Features

  • Multiple targets can be configured
  • Enterprise Library Configuration Console available for easy configuration
  • Large number of options to be configured may make it a bit daunting to start with
  • Invasive – requires code change to implement logging
  • Logs all kinds of events/information, not just for error logging
  • Formatters available for formatting the event message
  • Log filters allow filtering of log messages
  • Facilities for WCF integration

 

Comparison with ELMAH

Feature/s Logging Application Block
ELMAH
Scope
  • True enterprise level exception handling framework, across layers, tiers, processes and services (in tandem with Exception Handling Application Block)
  • Logs all kinds of events, not just exceptions
  • Lightweight logging framework with extension points for ASP.NET web applications
  • By default logs unhandled exceptions
  • Error signaling allows handled exceptions to be logged
  • No support for non-error messages
Targets supported
  • The event log
  • An e-mail message
  • A database (supports multiple)
  • A message queue
  • A text file
  • A Windows® Management Instrumentation (WMI) event
  • Custom locations using application block extension points
  • Microsoft SQL Server
  • Oracle (OracleErrorLog)
  • SQLite (version 3) database file
  • Microsoft Access (AccessErrorLog)
  • Loose XML files
  • RAM (in-memory)
  • SQL Server Compact Edition
  • MySQL
  • PostgreSQL
Pluggable? No. Requires careful configuration and implementation in code Fully pluggable out of the box, requires only configuration for basic features
Configuration
  • XML configuration in the app.config/web.config as applicable
  • Enterprise Library Configuration Console tool available for ease in configuration
XML configuration in the web.config
Intrusiveness Requires code change for implementation No code change required for basic features
Extensibility
  • Easily extensible with multiple points for extensibility
  • Easy to extend for log message formatting and contextual information
  • No source code change required
  • Requires change to source code for any kind of extensibility
  • Error message formatting and contextual information addition requires source code changes
Scalability
  • Easily scales for small to medium sized applications
  • Not enough data available for large sized applications
Requires more research

 

Summary

The Logging Application block beats ELMAH hands down in comprehensiveness. It can be used for logging all kinds of messages from all layers of various kinds of applications including ASP.NET, windows forms, WCF services etc. It can also be used for tracing for performance and debugging purposes.

On the other hand ELMAH is a light-weight framework for logging exceptions in ASP.NET applications.

ELMAH is very easy to configure and use. It is fully pluggable. Whereas implementation of the Logging Application block requires careful planning, configuration and is intrusive as it requires changes to code wherever logging is required.

One of the biggest benefits of the Enterprise Library is that it works in tandem with the Exception Handling block to implement a consistent strategy for processing exceptions in all the architectural tiers of an enterprise application including WCF Services.

While ELMAH is perfect for ASP.NET applications, for enterprise applications the Enterprise Library fulfills the comprehensiveness required.

References:-

  1. http://msdn.microsoft.com/en-us/library/ff664569%28v=pandp.50%29.aspx
  2. http://www.codeproject.com/Articles/9545/Get-Logging-with-the-Enterprise-Library
  3. THE ELMAH REPORT
  4. http://msdn.microsoft.com/en-us/library/ff664698%28v=pandp.50%29.aspx
  5. http://stackoverflow.com/questions/766610/how-to-get-elmah-to-work-with-asp-net-mvc-handleerror-attribute/5936867#5936867
  6. http://code.google.com/p/elmah/wiki/DotNetSlackersArticle#Logging
  7. http://mikee.se/Archive.aspx/Details/elmah_on_steroids_20100403

Web service interoperability issue

We have a legacy web service implemented in Java which was recently updated to add an additional flavor to some existing transaction. The result was that we needed to consume both the old web method and the new one from different parts of the same application.

If you are trying to call a web service developed in a technology different from that of .NET, there is one thing that you need to keep in mind, especially if you have a very distributed environment with a lot of web services and have different implementations of the same web method. This is an issue that is only encountered with a .NET proxy client when referencing a non-.NET web service and when the web methods differ only by the SOAP action header. Yes, certain technologies other than .NET, allow a web service provider to create a web service with multiple methods with the same wire signature, differing only by the SOAP action header.

This is a valid scenario as often the web service developer would like to share the schema especially in the cases where the web methods differ only by the implementation and primarily meant to be different flavors of the same transaction.

In a wsdl such operations might be defined as follows:-

<wsdl:operation name=”Method1″>
<soap:operation soapAction=”Method1SOAPAction” style=”document”/>
<wsdl:input>
<soap:body use=”literal”/>
</wsdl:input>
<wsdl:output>
<soap:body use=”literal”/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name=”Method2″>
<soap:operation soapAction=”Method2SOAPAction” style=”document”/>
<wsdl:input>
<soap:body use=”literal”/>
</wsdl:input>
<wsdl:output>
<soap:body use=”literal”/>
</wsdl:output>
</wsdl:operation>

The problem here is that when adding a web reference to such a web service, Visual Studio does not throw an error and allows you to create the web reference successfully. However, during runtime it fails while instantiating the proxy and instead throws an exception. The details of such an exception would look as below:-

System.InvalidOperationException: Method TestWebReference.SecondOperationName can not be reflected. —> System.InvalidOperationException: The XML element ‘DuplicateElementName’ from namespace ‘http://tempuri.org/Transactions/schemas’ references a method and a type. Change the method’s message name using WebMethodAttribute or change the type’s root element using the XmlRootAttribute.\r\n   at System.Xml.Serialization.XmlReflectionImporter.ReconcileAccessor(Accessor accessor, NameTable accessors)\r\n   at System.Xml.Serialization.XmlReflectionImporter.ImportMembersMapping(String elementName, String ns, XmlReflectionMember[] members, Boolean hasWrapperElement, Boolean rpc, Boolean openModel, XmlMappingAccess access)\r\n   at System.Web.Services.Protocols.SoapReflector.ImportMembersMapping(XmlReflectionImporter xmlImporter, SoapReflectionImporter soapImporter, Boolean serviceDefaultIsEncoded, Boolean rpc, SoapBindingUse use, SoapParameterStyle paramStyle, String elementName, String elementNamespace, Boolean nsIsDefault, XmlReflectionMember[] members, Boolean validate, Boolean openModel, String key, Boolean writeAccess)\r\n   at System.Web.Services.Protocols.SoapReflector.ReflectMethod(LogicalMethodInfo methodInfo, Boolean client, XmlReflectionImporter xmlImporter, SoapReflectionImporter soapImporter, String defaultNs)\r\n   — End of inner exception stack trace —\r\n   at System.Web.Services.Protocols.SoapReflector.ReflectMethod(LogicalMethodInfo methodInfo, Boolean client, XmlReflectionImporter xmlImporter, SoapReflectionImporter soapImporter, String defaultNs)\r\n   at System.Web.Services.Protocols.SoapClientType.GenerateXmlMappings(Type type, ArrayList soapMethodList, String serviceNamespace, Boolean serviceDefaultIsEncoded, ArrayList mappings)\r\n   at System.Web.Services.Protocols.SoapClientType..ctor(Type type)\r\n   at System.Web.Services.Protocols.SoapHttpClientProtocol..ctor()\r\n   at TestApplication.TestWebReference. TestWebReference..ctor() in C:\\DOTNET\\ASP.NET\\ TestApplication\\Web References\\ TestWebReference\\Reference.cs:line 39\r\n   at TestApplication._Default.Page_Load(Object sender, EventArgs e) in C:\\DOTNET\\ASP.NET\\TestApplication\\Default.aspx.cs:line 16

When using the Web Services Description Language Tool – wsdl.exe to generate a proxy, it actually displays a warning describing the problem. However, it still generates the proxy. I fail to understand what is the purpose of a proxy that cannot be instantiated. Besides, Visual Studio does not even show any warnings. That is very disappointing.

Microsoft (R) Web Services Description Language Utility

[Microsoft (R) .NET Framework, Version 4.0.30319.1]

Copyright (C) Microsoft Corporation. All rights reserved.

Warning: This web reference does not conform to WS-I Basic Profile v1.1.

R2710: The operations in a wsdl:binding in a DESCRIPTION MUST result in wire signatures that are different from one another. An endpoint that supports multiple operations must unambiguously identify the operation being invoked based on the input message that it receives. This is only possible if all the operations specified in the wsdl:binding associated with an endpoint have a unique wire signature.

–  Input message ‘OperationSoapIn’ from namespace ‘http://tempuri.org/Transactions/schemas’ has wire signature ‘http://tempuri.org/Transactions/schemas:DuplicateElementName’.

–  Input message ‘OperationSoapIn’ from namespace ‘http://tempuri.org/Transactions/schemas’ has wire signature ‘http://tempuri.org/Transactions/schemas:DuplicateElementName’.

For more details on the WS-I Basic Profile v1.1, see the specification at http://www.ws-i.org/Profiles/BasicProfile-1.1.html.

Writing file ‘C:\DOTNET\ASP.NET \TestWebReference.cs’.

It seems during instantiation of the proxy, the .NET runtime uses Reflection to create various types presumably for serialization purposes and hence based on the SOAP messages to be emitted on the wire. It seems like this process fails for some reason, presumably due to a name clash, during the processing of the second operation.

What this means, is that even if you specify a WebMethodAttribute or XMLRootAttribute as suggested in the exception message, it still fails during instantiation of the proxy to create two different classes of the same name within the same namespace.

So far the only solution is to change the schema or namespace in the web service so that the SOAP wire signature of the two operations is different. Or a more time consuming one would be to not use a web reference at all.

This problem has also been discussed here:-

SQL Server Service Broker – An introduction

Service Broker was introduced in SQL Server 2005 as a way to provide a messaging solution integrated into the database so that it becomes very easy to incorporate messaging and especially transactional messaging into your database applications. These so-called “Messages” are always sent asynchronously, and can be sent between services on the same database, different databases on the same server instance or even different server instances.

This article is a tutorial on how to use Service Broker to build a very simple messaging application. For simplicity, I am considering both the services to be in the same database.

Creating the Message types:-

create message type [//Fund/FundAdministrator/RequestMsg]
validation = well_formed_xml;
GO

This will create a message type which forms the request message which is sent from the initiator service (the requestor) to the target service (the responder).

create message type [//Fund/FundAdministrator/ResponseMsg]
validation = well_formed_xml;
GO

This will create the response message type. This is the message type which is sent from the Target to the Initiator in response to //Fund/FundAdministrator/RequestMsg.

Here, both the request message type and response message type are in URI format. That is merely a convention and definitely not necessary. If you are implementing a service broker application where both the Initiator and the Target are on the same database instance, you are better-off giving simpler meaningful names.

Creating the Contracts:-

CREATE CONTRACT [//Fund/FundAdministrator/FundContract]
([//Fund/FundAdministrator/RequestMsg]
SENT BY INITIATOR,
[//Fund/FundAdministrator/ResponseMsg]
SENT BY TARGET
);
GO

This defines a contract which associates what message type is sent by the Initiator and which message type is a contract.
Thus, a conversation implements a contract which in turn identifies the types of message exchanged by the Initiator and Target.

Creating the Queues:-

CREATE QUEUE FAInitiatorQueue;
GO

CREATE QUEUE FATargetQueue;
GO

This creates the Initiator and Target queues. Queues are merely implemented as tables in SQL Server to the support the Service Broker architecture. They implementing ordering of the messages. They also protect the messages from direct modification by any database users.

Creating the Services:-

CREATE SERVICE
[//Fund/FundAdministrator/FAInitiatorService]
ON QUEUE FAInitiatorQueue;
GO

CREATE SERVICE
[//Fund/FundAdministrator/FATargetService]
ON QUEUE FATargetQueue
([//Fund/FundAdministrator/FundContract]);
GO

This creates the Initiator and Target services. Note, the Target service, besides specifying which queue does it receive the messages in, it also specifies the Contract defined earlier. This restricts the Target Service to allow conversations pertaining only to that defined contract.

Send a request from Initiator:-

BEGIN

DECLARE @DialogHandle UNIQUEIDENTIFIER;

BEGIN DIALOG @DialogHandle
FROM SERVICE
[//Fund/FundAdministrator/FAInitiatorService]
TO SERVICE
‘//Fund/FundAdministrator/FATargetService’
ON CONTRACT
[//Fund/FundAdministrator/FundContract]

DECLARE @RequestMsg NVARCHAR(1000)
set @RequestMsg = ‘<Fund>XYZ</Fund>';

SEND ON CONVERSATION @DialogHandle
MESSAGE TYPE [//Fund/FundAdministrator/RequestMsg]
(@RequestMsg);

END
GO

This sends a request from the Initiator to the Target. Note the Request Dialog handle that is required. It is a UniqueIdentifier. Before starting the conversation (sending the request), a dialog needs to be established describing the Initiator, Target and Contract. The “Send On Conversation” statement sends the request.

Receive a Request at the Target:-

DECLARE @DialogHandle UNIQUEIDENTIFIER;
DECLARE @ReceivedMsg NVARCHAR(1000);

BEGIN

RECEIVE TOP(1)
@DialogHandle = conversation_handle,
@ReceivedMsg = message_body
FROM FATargetQueue;

BEGIN

–Process Fund here

DECLARE @ResponseMsg NVARCHAR(1000);
SELECT @ResponseMsg = ‘<ResponseMsg>Fund Processed successfully</ResponseMsg>';

SEND ON CONVERSATION @DialogHandle
MESSAGE TYPE
[//Fund/FundAdministrator/ResponseMsg]
(@ResponseMsg);

END CONVERSATION @DialogHandle

END

END
GO

The Target receives the request message (in this case the Fund name) and the converstaion handle. It then processes the fund and sends the response message back to the same conversation handle. Note, it also ends the Target side of the Conversation.

Initiator receives the response:-

DECLARE @ResponseMsg NVARCHAR(1000);
DECLARE @DialogHandle UNIQUEIDENTIFIER;

BEGIN

RECEIVE TOP(1)
@DialogHandle = conversation_handle,
@ResponseMsg = message_body
FROM FAInitiatorQueue

END CONVERSATION @DialogHandle

END
GO

Here, the Initiator receives the response and finally closes the conversation at its end.

This demonstrates a very simple scenario of request from the Initiator to the Target and a response back from the Target to the Initiator.

There are tremendous benefits and uses of the Service broker. Here are a few references to the same:-

  1. http://msdn.microsoft.com/en-us/library/ms345108%28SQL.90%29.aspx
  2. http://msdn.microsoft.com/en-us/library/ms166071.aspx

xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"

There was a bug with both with the Beta version of VS 2005 and also the Website Administration Tool which caused the above schema attribute to be added to the root “Configuration” tag of the web.config. You can go through the first three References at the bottom of this article for a more detailed description of the problem.

Until now I was under the impression, that this bug only affected VS 2005 Intellisense while editing the web.config. However, recently I encountered another more serious issue which occurred at runtime due to this additional schema tag being present in the web.config. It so happens, that with this tag being present, the “codeBase” hint specified in the web.config does not take any effect on the assembly probing mechanism of the runtime to resolve an assembly reference.

The codeBase hint is typically configured as follows to specify a path for the runtime to probe for referenced files:-

codeBase Hint configuration

In the above example, for the 1.0.0.0 version of the assembly, the codeBase specified the 1.0 folder within the bin folder and for the 1.0.0.1, it specifies the 1.1 folder. That is to say, once the runtime determines the correct assembly version required, it checks if that assembly version has been bound before, checks the global assembly cache successively and if it does not find a match in either, then it looks at the location specified by the codeBase hint.

However, with the additional namespace tag specified in the root “Configuration” tag, the runtime completely ignored the codeBase hint and did not look for the assembly in the specified path even though it could not find the required version of the assembly in the previously bound paths or the GAC. As a result, one of the following two errors would result:-

  1. Could not load file or assembly ‘Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=76cd4ba45e0a88a1’ or one of its dependencies. System could not find the file.
  2. Could not load file or assembly ‘Utility, Version=1.2.0.200, Culture=neutral, PublicKeyToken=764d581291d764f7′ or one of its dependencies. The located assembly’s manifest definition does not match the assembly reference.

The solution is pretty simple. Just remove the namespace tag from the root “Configuration” tag.

References:-

  1. http://forums.asp.net/p/981068/1359525.aspx
  2. http://groups.google.de/group/microsoft.public.dotnet.framework.aspnet/browse_thread/thread/12152d90b4f6398c/076c50ae9d71f18f?lnk=st&q=web.config+author%3AJooss&rnum=1&hl=de
  3. http://weblogs.asp.net/scottgu/archive/2005/12/02/432077.aspx
  4. http://msdn.microsoft.com/en-us/library/yx7xezcf%28vs.71%29.aspx