Posts Tagged ‘service’

Apple reported 10 millions registered users (of its 800 millions iTunes accounts) for its Music service following the first month (June 30 to end of July). We can suppose there were additional 5 millions registrations in August, then 3 millions in September, and 2 millions the first half of September. This could then match with Apple’s announce mid October stating their were 15 millions still opened Music accounts (and 6.5 millions paid accounts among these).

Apple offered an option to disable automatic renewal of Music subscription, then many users diddn’t wait the 3 months trial ending to cancel (or not) their subscription, they just let it stop by itself in case they wouldn’t renew. Did Apple take into account the users that  left the automatic renewal on for its 6.5 paid accounts ?

On one hand their may be 100% of early “subscribers” (the about 5 millions ones that entered trial bewteen June 30 and mid July) that let their subscription stop by mid October, that could explain the 15 millions active accounts (from 20 millions total trials) reported at that time.

On another hand there should have been at least the same amount that would have renewed their subscription to reach the stated 6.5 paid accounts (most of them would have choosed to renew a few days to one week before trial ending, that is early to mid October). Apple offered an option to initially extend and pay for many months, however few users may have opted for this. Then these same users couldn’t both have renewed and let stop their subscription.

Apple then may have taken into account users that let the automatic renewal option enabled. There shouldn’t be more than 2 millions users that did renew their subscription for some months, that is only 10% of users that entered the trial (and 0.25% of Apple’s iTunes users).

Considering the deceiving quality of the service (iTunes Store is much better and many songs or artists weren’t present in Music service), Apple should lower the price, replace the service by access to the full ITMS catalog, and provide songs in lossless format (a new HD audio format is expected by Apple early 2016).

Also many would have used the trial to copy most of songs (using Soundflower), then Apple shouldn’t provide a Trial (as users still can try iTunes Store by listening to long tracks samples).

 

A new 1.1 version of CP2JavaWS (Cappuccino to remote Java services framework) is available here. It includes the following new features/enhancements :

– Added Basic Authentication scheme besides Digest, and a generic Active Directory/Ldap authentication service (automatic check of user password and retrieve of its profiles related to the application from the directory, that are then stored on the client side’s endpoint for UI conditional display – besides being used on the server side from the authorization service).

– global authentication to an endpoint (in order to allow connect/disconnect menu for login/logout) besides per service check, by calling a dummy service listed in authenticated services (needed to keep – not duplicate – authentication process managed by the authentication filter).

– better error management, and easy to read full server error trace in the client’s alert window.

– parameter to set the encoding information sent from the Json filter to the client (depends from encoding used in custom services and/or database).

The final version (1.0) of CP2JavaWS is available :

Added support for service protocol (CP class with methods signatures) specifying when retrieving a proxy, in order to allow :
– arguments type check
– nil arguments values (the expected type can then be retireved from the protocol – required for Java reflect)
– generic methods arguments (CPObject in CP, Object in Java)

Renamed HabiltationService/Filter to AuthorizationService/Filter.

Bug fix in CP2JavaWSJSONPConnection (synch. with latest code since addition of URL class).

MasterDetailView now uses alternating row color for table view, and background for detail view .

Note : documentation has been moved to MediaWiki.

A new version of CP2JavaWS is available at sourceforge :

Note : now uses json2lib stringify and parse methods from latest Cappuccino main branch (and future 0.71 version). Then it does not work for version 0.7 (or you should replace these methods manually by these from CPValue).
These two new methods should lead to general better performance.

– fixed a cache problem : now if an asynchronous request was pending before a cache fault, its return is ignored (as the state isn’t the same as originally expected after a cache fault).

– the sorting code now works properly (as soon as headers and CPSortDescriptors are added to CPTableView). It can still be tested by modifying the init value for currentSortDescriptorsStr in CP2JavaWSTableViewDelegate (see commented code). The reference is now the position in the table, and limit(first, length) requests are used.

– added a new generic service, GenericMasterDetailDAOService, that manages retrieving of elements for any CP class, using Hibernate. It then avoids having to define a DAO service (the previous mode is still available, for custom management or non-database datastores).

To use the new mode, pass the table elements CP class name when creating the CP2JavaWSTableViewDelegate, instead size and read method names (that are then generic).

CP2JavaWS is a bridge between Cappuccino applications and Java services deployed on a webapp. It consists of a client proxy (CP class based on CPInvocation forwarding) and servlet filters,  and provides these features :

– support for encoding/decoding of complex objects graphs (including nested collections with heterogeneous elements), with references/cycles management (using paths and a CPPropertyUtils class that provides exactly the same features as BeanUtils 1.8). Also supports CPCoding protocol if specific CP/JSON mapping is required (usefull when attributes names for remote Java classes are different from CP ones).

– support for arguments types check, nil arguments, generic arguments types (CPObject/Object) by specifying a service protocol (CP class) when retreiving a proxy.

– automatic switch to JSONP mode when calling a remote service on another endpoint (except when working locally with Safari – not required).

– full digest authentication management (native browser authentication dialog or custom CP view – a default implementation is provided). The original request is sent automatically after authentication success. The server-side authentication filter allows many settings.

– habilitation filter (for finer service’s methods access control once user is authenticated).

– full jsession id tracking (sent along subsequent requests to a endpoint we authenticated to), that also allows composite applications (made from parts using remote services from different endpoints). That is close to the principle of Apple’s OpenDoc and recent Google’s wavelets.

– provided CPTableView delegate (datasource) that allows automatic browsing of large remote service’s collection result, without page break and without pause (thanks to an asynchronous read-ahead mechanism). It manages sorting (headers however not displayed yet – waiting for the new CPTableView implementation) and custom selection criterias, through a generic DAO component on the server-side (based on Hibernate).

– Direct2CP feature : it provides automatic generation of master (table) and detail views, and edit/insert/delete management, by just setting the elements CP class (that mode uses internally the previous CPTableView delegate and generic Java remote DAO service). A custom detail view can be used instead the generic/generated one (has then to implement some delegate methods to benefit from the provided detail view controller and remote DAO service). A custom service can also be used instead of the generic DAO service (if using a non relational datastore or connector).

Demo : the distribution includes a working example that features custom objects and nested collections arguments with cycle, default CP authentication dialog, demo authentication and habilitation services, and Direct2CP mode. It is also available online at Google AppEngine :

CP2JavaWS online demo

This framework is provided under the GNU LGPL license.

Usage


On the client-side :

var endPoint = [CP2JavaWSEndPoint
createForURL:"http://host/appName/endPoint"];
var remoteService = [endPoint
proxyForJavaServiceInterface:"com.cp2javaws.demo.services.
IDemoService1" delegate:self];
[remoteService method1:"arg1StringValue"
andArg2:2 andArg3:myCustomObject delegateRespHandler:@selector(successHandler1:) delegateFailHandler:@selector(failHandler1:)];

There isn’t any limitation in types and count of passed arguments. By default the first selector part when calling remote service’s method is the method’s name (Java name), and following selector parts can be named as we want (don’t have any equivalent on the Java server side method’s signature). We can however use setUsesFullSelectorName method on the proxy service to use the full selector parts as the remote service’s method name (default mode when specifying a protocol – see below).
Supported collections for call arguments and return objects graphs are CPArray (List) and CPDictionary (Map), and they can be nested at any depth. Moreover heterogeneous collection elements are allowed (can also be custom objects or other collections…).

We can pass a protocol (CP class with methods signatures) when retreiving the proxy, in order to allow arguments check, nil arguments values, and generic arguments types (CPObject/Object) :

var remoteService = [endPoint1 proxyForJavaServiceInterface:@"com.cp2javaws.demo.services.IDemoService1" objjProtocol:"Service1Protocol" delegate:self];

Service protocol example :
@implementation Service1Protocol : CPObject {}
-(CPArray) readForAa:(MyCustomClass)aCustom Bb:(CPArray)aArray Cc:(CPDictionary)aDictionary Dd:(CPInteger)aInt Ee:(CPString)aStr Ff:(BOOL)aBool Gg:(CPDecimal)aDEC Hh:(CPDate)aDate Ii:(CPObject)aGeneric {}

 

On the server-side :

Just add the cp2javaws-filter.jar and the service factory support jar (for example cp2javaws-springsupport.jar) in the application’s WEB-INF/lib (along with json-lib-2.2.3-jdk13.jar, Jakarta commons-lang 2.4, commons-beanutils 1.8.0, commons-collections 3.2, commons-logging 1.1.1, ezmorph 1.0.6, and base spring.jar – 2.8 Mo – if Spring factory). The cp2javaws-filter.jar and cp2javaws-springsupport.jar have been compiled using JDK 1.5 (recompile with provided source if needed).

For custom service factory/framework, a listener example is provided (see server source code, DummyContextWrapperListener.java and DummyContextWrapper.java). Just modify these classes to get you service factory injected, and then export these two classes into a support.jar (the same as with cp2javaws-springsupport.jar).

Add the following config to the web.xml (this example uses Spring factory) :


<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>
com.cp2javaws.listeners.SpringContextWrapperListener
</listener-class>
</listener>
<filter>
<filter-name>CPJSonFilter</filter-name>
<filter-class>
com.cp2javaws.filters.CPJSonFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>CPJSonFilter</filter-name>
<url-pattern>/CP2JavaWSEndpoint1</url-pattern>
</filter-mapping>

Add the factory config file in the web application (for example applicationContext.xml in WEB-INF if Spring, with configured services beans).

A mapping file (see provided example) has to be put on the server-side for custom Objective-J objects to Java custom objects class names mapping.

Digest authentication filter configuration

See included example webapp web.xml.

Authorization filter configuration

See included example webapp web.xml.

Why using JSON / namespace consideration / CP2JavaWS comparison with GWT / Spring 3 REST servlet

JSON is intended to be used as a simple serialization format for REST exchanges, so it doesn’t manage namespace problematics. We can read a useful article about its limitations and read a thread that explores possible extensions for JSON to be namespace aware :
http://blogs.sun.com/bblfish/entry/the_limitations_of_json
http://groups.google.com/group/json-schema/browse_thread/thread/dd1a8c9e55035c67

A more robust solution would have been to use a format such as XStream one (that I have used extensively on other projects from Java dynamic proxies), but it would have required an Objective-J implementation of that framework. Like Ojbective-C, Objective-J still provides its own object serialiazation format through coders (objects data are available as CPData). However on the other side (Java server) an implementation would have also been required.

GWT doesn’t face this problem as the client code (generated into javascript) is written in Java, so the generation tool can use the same serialization Java APIs (furthermore each service parameter object is defined only once. With CP2JavaWS it has to be defined both in Java and in Objective-J). However the powerful (and fully tested since NeXT era) AppKit/FoundationKit frameworks and Interface Builder/Atlas tools available in Cappuccino overcome that little overhead.
Moreover Cappuccino allows mixing Objective-J code and javascript code (in a completely transparent manner, as Objective-C with C/C++ code), that allows to reuse existing js libraries and easily include accessibility features (are being introduced in modern browsers).
GWT uses a generation step to allow client-side javascript<–>JSON serializers/deserializers generation, as they have to be static (are javascript code). Objective-J runtime dynamic feature doesn’t require any manual generation step, as the end javascript is produced at execution time.

The Spring project also plans to provide such of REST bridge servlet for Spring 3 version, and the namespace problematics are widely discussed. We can find an example of JSON to Spring beans request parameters mapping servlet here : http://weblogs.java.net/blog/rexyoung/archive/2008/11/how_to_bind_fro.html.

Why not a Java to Objective-J generation tool for Cappuccino, like with GWT ?

Such tool allows far more easier development of the solution, it can lead to more optimized code (faster because of static code produced, no dynamic feature) and it allows writing code in Java (and business objects used as services’s parameters and return are declared only one time). However it breaks the development cycle and isn’t elegant.

After all, what would we say if object-relationnal mapping frameworks required to use a tool to generate some DAO from the mapping files ? Instead they use reflection APIs to dynamically generate objects from mapping description files. I know some implementations (based on the JDO specification) are based on a bytecode enhancement step (to compare with GWT generation step), that allows datastore type abstraction (database, but also filesystem, CICS, etc.) and better performance. But the result is that most people stayed with standard reflection based solutions (notably Hibernate, a defacto standard – not even based initially on any specification…)

Google had no other way to make GWT work than to use a generation step, because their end client code is pure javascript (so no way to implement such remote service proxy). Thanks to Cappuccino Objective-C runtime (converts Objective-J code into javascript at runtime using a JIT pre-interpreter), the proxy could be implemented without requiring a generation step.