ServiceStack v4.0.52

We've hope everyone's had a great X-mas holidays and are super-charged for a productive 2016!

To kick things off we're making your ServiceStack Services even more attractive to mobile and Java developers with first-class support for JetBrains modern and highly-productive Kotlin programming language including integration into Android Studio and enhanced support in Android and JsonServiceClients.

Kotlin - a better language for Android and the JVM

Whilst Java is the flagship language for the JVM, it's slow evolution, lack of modern features and distasteful language additions have grown it into an cumbersome language to develop with, as illustrated in the C# 101 LINQ Examples in Java where it's by far the worst of all modern languages compared, making it a poor choice for a functional-style of programming that's especially painful for Android development which is stuck on Java 7.

101 LINQ Examples in Kotlin vs Java

By contrast Kotlin is one of the best modern languages for functional programming that's vastly more expressive, readable, maintainable and safer than Java. As Kotlin is being developed by JetBrains it also has great tooling support in Android Studio, IntelliJ and Eclipse and seamlessly integrates with existing Java code where projects can mix-and-match Java and Kotlin code together within the same application - making Kotlin a very attractive and easy choice for Android Development.

Kotlin Native Types!

As we expect more Android and Java projects to be written in Kotlin in future we've added first-class Add ServiceStack Reference support for Kotlin with IDE integration in Android Studio and IntelliJ IDEA where App Devlopers can create and update an end-to-end typed API with just a Menu Item click - enabling a highly-productive workflow for consuming ServiceStack Services!

No new IDE plugins were needed to enable Kotlin support which was added to the existing ServiceStack IDEA plugin that can Install or Updated to enable Kotlin ServiceStack Reference support in Android Studio or IntelliJ IDEA.

Installing Kotlin

Kotlin support is enabled in Android Studio by installing the JetBrain's Kotlin plugin in project settings:

After it's installed, subsequent Restarts of Android Studio will now load with the Kotlin plugin enabled.

Configure Project to use Kotlin

After Kotlin is enabled in Android Studio you can configure which projects you want to have Kotlin support by going to Tools -> Kotlin -> Configure Kotlin in Project on the File Menu:

Configuring a project to support Kotlin just modifies that projects build.gradle, applying the necessary Android Kotlin plugin and build scripts needed to compile Kotlin files with your project. Once Kotlin is configured with your project you'll get first-class IDE support for Kotlin .kt source files including intellisense, integrated compiler analysis and feedback, refactoring and debugging support, etc.

One convenient feature that's invaluable for porting Java code and learning Kotlin is the Converting Java to Kotlin Feature which can be triggered by selecting a .java class and clicking Ctrl + Alt + Shift + K keyboard shortcut (or using Find Action).

Kotlin Add ServiceStack Reference

To add a ServiceStack Reference, right-click (or press Ctrl+Alt+Shift+R) on the Package folder in your Java sources where you want to add the POJO DTO's. This will bring up the New > Items Context Menu where you can click on the ServiceStack Reference... Menu Item to open the Add ServiceStack Reference Dialog:

Add ServiceStack Reference Kotlin Context Menu

The Add ServiceStack Reference Dialog will be partially populated with the selected Package with the package where the Dialog was launched from and the File Name defaulting to dtos.kt where the generated Kotlin DTO's will be added to. All that's missing is the url of the remote ServiceStack instance you wish to generate the DTO's for, e.g: https://techstacks.io:

Clicking OK will add the dtos.kt file to your project and modifies the current Project's build.gradle file dependencies list with the new net.servicestack:android dependency containing the JSON ServiceClients which is used together with the remote Servers DTO's to enable its typed Web Services API. If for some reason you wish to instead add Java DTO's to your project instead of Kotlin, just rename the dtos.kt file extension to dtos.java and it will import Java classes instead.

As the Module's build.gradle file was modified you'll need to click on the Sync Now link in the top yellow banner to sync the build.gradle changes which will install or remove any modified dependencies.

Update ServiceStack Reference

Like other Native Type languages, the generated DTO's can be further customized by modifying any of the options available in the header comments:

/* Options:
Date: 2015-04-17 15:16:08
Version: 1
BaseUrl: https://techstacks.io

Package: org.layoric.myapplication
GlobalNamespace: techstackdtos
//AddPropertyAccessors: True
//SettersReturnThis: True
//AddServiceStackTypes: True
//AddResponseStatus: False
//AddImplicitVersion: 
//IncludeTypes: 
//ExcludeTypes: 
//DefaultImports: java.math.*,java.util.*,net.servicestack.client.*,com.google.gson.annotations.*
*/
...

For example the package name can be changed by uncommenting the Package: option with the new package name, then either right-click on the file to bring up the file context menu or use Android Studio's Alt+Enter keyboard shortcut then click on Update ServiceStack Reference to update the DTO's with any modified options:

JsonServiceClient Usage

Both Java and Kotlin use the same JsonServiceClient that you need to initialize with the BaseUrl of the remote ServiceStack instance you want to access, e.g:

val client = JsonServiceClient("https://techstacks.io")

The JsonServiceClient is made available after the net.servicestack:android package is automatically added to your build.gradle when adding a ServiceStack reference.

Typical usage of the Service Client is the same in .NET where you just need to send a populated Request DTO and the Service Client will return a populated Response DTO, e.g:

val response:AppOverviewResponse? = client.get(AppOverview())
val allTiers:ArrayList<Option> = response.AllTiers
val topTech:ArrayList<TechnologyInfo> = response.TopTechnologies

As Kotlin has proper type inference, the explicit types are unnecessary. Here's a typical example using a populated Request DTO:

var request = GetTechnology()
request.Slug = "servicestack"

val response = client.get(request)

Custom Route Example

When preferred you can also consume Services using a custom route by supplying a string containing the route and/or Query String. As no type info is available you'll need to specify the Response DTO class to deserialize the response into, e.g:

val response = client.get("/overview", OverviewResponse::class.java)

//Using an Absolute Url:
val response = client.get("https://techstacks.io/overview", OverviewResponse::class.java)

AutoQuery Example Usage

You can also send requests composed of both a Typed DTO and untyped String Map by providing a Hash Map of additional args. This is typically used when querying implicit conventions in AutoQuery services, e.g:

val response = client.get(FindTechnologies(), hashMapOf(Pair("DescriptionContains","framework")))

AndroidServiceClient Async Usage

To make use of Async API's in an Android App (which you'll want to do to keep web service requests off the Main UI thread), you'll instead need to use an instance of AndroidServiceClient which as it inherits JsonServiceClient can be used to perform both Sync and Async requests which can be instantiated with:

val client = AndroidServiceClient("https://techstacks.io")

To provide an optimal experience for Kotlin and Java 8, we've added SAM overloads using the new AsyncSuccess<T>, AsyncSuccessVoid and AsyncError interfaces which as they only contain a single method are treated like a lambda in Kotlin and Java 8 allowing you to make async requests with just:

client.getAsync(Overview(), AsyncSuccess<OverviewResponse> {
        var topUsers = it.TopUsers
    }, AsyncError {
        it.printStackTrace()
    })

Instead of the previously more verbose anonymous AsyncResult interface used in Java 7:

client.getAsync(Overview(), object: AsyncResult<OverviewResponse>() {
    override fun success(response: OverviewResponse?) {
        var topUsers = response!!.TopUsers
    }
    override fun error(ex: Exception?) {
        ex?.printStackTrace()
    }
})

Custom Service Examples

Just like the JsonServiceClient Sync examples above there a number of flexible options for executing Custom Async Requests, e.g:

//Relative Url:
client.getAsync("/overview", OverviewResponse::class.java,
    AsyncSuccess<OverviewResponse?> {  
    })

//Absolute Url:
client.getAsync("https://techstacks.io/overview", OverviewResponse::class.java,
    AsyncSuccess<OverviewResponse>() {
    })

//AutoQuery Example:
client.getAsync(FindTechnologies(), hashMapOf(Pair("DescriptionContains", "framework")),
    AsyncSuccess<QueryResponse<Technology>>() {
    })

Download Raw Image Async Example

Example downloading raw Image bytes and loading it into an Android Image Bitmap:

client.getAsync("https://servicestack.net/img/logo.png", {
    val img = BitmapFactory.decodeByteArray(it, 0, it.size);
})

Send Raw String or byte[] Requests

You can easily get the raw string Response from Request DTO's that return are annotated with IReturn<string>, e.g:

open class HelloString : IReturn<String> { ... }

var request = HelloString()
request.name = "World"

val response:String? = client.get(request)

You can also specify that you want the raw UTF-8 byte[] or String response instead of a the deserialized Response DTO by specifying the Response class you want returned, e.g:

val response:ByteArray = client.get("/hello?Name=World", ByteArray::class.java);

Typed Error Handling

Thanks to Kotlin also using typed Exceptions for error control flow, error handling in Kotlin will be instantly familiar to C# devs which also throws a typed WebServiceException containing the remote servers structured error data:

var request = ThrowType()
request.Type = "NotFound"
request.message = "not here"

try {
    val response = client.post(request)
} catch(webEx: WebServiceException) {
    val status = webEx.responseStatus
    status.message    //= not here
    status.stackTrace //= (Server StackTrace)
}

Async Error Handling

Whilst Async Error handlers can cast into a WebServiceException to access the structured error response:

client.postAsync(ThrowError(), AsyncSuccess<ThrowErrorResponse> { },
    AsyncError {
        val webEx = it as WebServiceException

        val status = webEx.responseStatus
        status.message    //= not here
        status.stackTrace //= (Server StackTrace)
    })

JsonServiceClient Error Handlers

To make it easier to generically handle Web Service Exceptions, the Java Service Clients also support static Global Exception handlers by assigning AndroidServiceClient.GlobalExceptionFilter, e.g:

AndroidServiceClient.GlobalExceptionFilter = ExceptionFilter { res:HttpURLConnection?, ex ->
}

As well as local Exception Filters by specifying a handler for client.ExceptionFilter, e.g:

client.ExceptionFilter = ExceptionFilter { res:HttpURLConnection?, ex ->
}

See the Kotlin Add ServiceStack Reference wiki for more docs on consuming ServiceStack Services from Kotlin.

Example TechStacks Android App

To demonstrate Kotlin Native Types in action we've ported the Java TechStacks Android App to a native Android App written in Kotlin to showcase the responsiveness and easy-of-use of leveraging Kotlin Add ServiceStack Reference in Android Projects.

Checkout the TechStacks Kotlin Android App repository for a nice overview of how it leverages Kotlin Native Types and iOS-inspired Data Binding to easily develop services-heavy Mobile Apps.

Kotlin Android Resources

To help getting started, here are some useful resources helping to develop Android Apps with Kotlin:

Improved Java and Android ServiceClient

Fewer dependencies

We've continued making improvements to Java and Android Service Clients which now have fewer dependencies initially triggered by Google removing Apache HTTP Client in Android 6.0. Previously the AndroidServiceClient net.servicestack:android package contained dependencies on the pure Java net.servicestack:client package as well as the external Apache Client. Both dependencies have been removed, the android package now uses the HTTP classes built into Android and all client classes have been merged into the android package.

The net.servicestack:client package continues to be available for pure Java clients and remains source-compatible with the JsonServiceClient classes in the android package.

Integrated Basic Auth

We've added HTTP Basic Auth support to JsonServiceClient following the implementation in .NET Service Client where you can specify the user's credentials and whether you always want to send Basic Auth with each request by:

client.setCredentials(userName, password);
client.setAlwaysSendBasicAuthHeaders(true);

TestAuthResponse response = client.get(new TestAuth());

It also supports processing challenged 401 Auth HTTP responses where it will transparently replay the failed request with the Basic Auth Headers:

client.setCredentials(userName, password);

TestAuthResponse response = client.get(new TestAuth());

Although this has the additional latency of waiting for a failed 401 response before sending an authenticated request.

Cookies-enabled Service Client

The JsonServiceClient now initializes a CookieManager in its constructor to enable any Cookies received to be added on subsequent requests to allow you to make authenticated requests after authenticating, e.g:

AuthenticateResponse authResponse = client.post(new Authenticate()
    .setProvider("credentials")
    .setUserName(userName)
    .setPassword(password));

TestAuthResponse response = client.get(new TestAuth());

OrmLite

Async PostgreSQL Support

The Npgsql ADO.NET PostgreSQL provider underwent a major upgrade in v3 where existing 2.x versions are now considered obsolete. As a result we've upgraded ServiceStack.OrmLite.PostgreSQL to use the latest v3.0.5 of Npgsql which is only available for .NET 4.5+ projects. We're also distributing .NET 4.0 builds of OrmLite in the same NuGet package but you'll need to manually reference the 2.x Npgsql dependency which contains .NET 4.0 .dll.

The primary benefit of upgrading means PostgreSQL now has true Async support where you can now use all of OrmLite's Async APIs with PostgreSQL! See ApiPostgreSqlTestsAsync.cs for a number of Async API's in action.

Parameterized SQL Expressions

When typed SQL Expressions were first added they constructed SQL inline. We've been slow to migrate to using parameterized queries which was first enabled for Oracle behind a OrmLiteConfig.UseParameterizeSqlExpressions = true; flag. We've since carefully maintained separate code-paths to ensure any migration efforts wouldn't affect existing queries. In the last release we extended support to SQL Server under the same flag.

In this release we've enabled it for every RDBMS provider and have made parameterized queries the default.

So now typed SQL Expressions will use parameterized queries by default, e.g:

db.Select<Person>(x => x.Age > 40);
db.GetLastSql(); //= SELECT "Id", "FirstName", "LastName", "Age" FROM "Person" WHERE ("Age" > @0)

For now all supported RDBMS's can still opt-in to revert to in-line SQL with:

OrmLiteConfig.UseParameterizeSqlExpressions = false;

db.Select<Person>(x => x.Age > 40);
db.GetLastSql(); //= SELECT "Id", "FirstName", "LastName", "Age" FROM "Person" WHERE ("Age" > 40)

However we've deprecated OrmLiteConfig.UseParameterizeSqlExpressions as we want to remove the legacy code-paths as soon as possible. Our entire test suite passes under either option so we expect this change to be a transparent implementation detail not affecting existing behavior. However if you do find any issues with this change please submit them to us as we plan to remove the legacy implementation if there aren't any reported issues. In the meantime you can use the above flag to revert to the existing behavior.

More examples showing the difference between in-line and parameterized SQL Expressions can be seen in:

Parameterized Updates

In the migration to Parameterized queries we've also migrated the Update API's, e.g:

db.Update(new Person { Id = 1, FirstName = "Jimi", LastName = "Hendrix" });
db.GetLastSql() //= UPDATE "Person" SET "FirstName"=@FirstName, "LastName"=@LastName WHERE "Id"=@Id

Parameterized ExecuteSql

The new ExecuteSql() API makes it easy to execute Custom SQL with parameterized values using an anon object:

Db.ExecuteSql("UPDATE page_stats SET fav_count = @favCount WHERE ref_id = @refId and ref_type = 'tech'",
              new { refId = techFav.Key, favCount = techFav.Value });

Whilst the Async alternative is useful for non-blocking fire-and-forget RDBMS updates, e.g. TechStacks uses this for updating page view counts:

Db.ExecuteSqlAsync("UPDATE page_stats SET view_count = view_count + 1 WHERE id = @id", new { id })

LoadSelect Typed Include References

Similar to LoadSingleById, there's now a typed API that lets you selectively load references in LoadSelect queries, e.g:

var customers = db.LoadSelect<Customer>(x => x.Name.StartsWith("A"), 
    include: x => new { x.PrimaryAddress });

Updated Stripe Gateway

StripeGateway has been updated to use the latest 2015-10-13 API version thanks to @jklemmack. Please refer to Stripe's API Chengelog for the complete list of API changes. Most of the API Collections now supports paging with the Limit, StartingAfter and EndingBefore properties added on the Request DTO's.

There were a few source-incompatible breaking changes where Cards have been renamed to Sources, Last4 was renamed to DynamicLast4 and the collection Count is renamed to TotalCount so to access the total size of a collection, instead of:

response.Cards.Count

You'd now use:

response.Sources.TotalCount

Customize urls used with IUrlFilter

Request DTO's can customize urls used in Service Clients or any libraries using ServiceStack's typed Reverse Routing by having Request DTO's implement IUrlFilter.

ServiceStack's Stripe Gateway takes advantage of ServiceStack's typed Routing feature to implement its Open-Ended, Declarative Message-based APIs with minimal effort.

In order to match Stripe's unconventional syntax for specifying arrays on the QueryString of their 3rd party REST API we use IUrlFilter to customize the url that's used. E.g. we need to specify include[] in order for the Stripe API to return any optional fields like total_count.

[Route("/customers")]
public class GetStripeCustomers : IGet, IReturn<StripeCollection<StripeCustomer>>, IUrlFilter
{
    public GetStripeCustomers() 
    {
        Include = new[] { "total_count" };
    }

    [IgnoreDataMember]
    public string[] Include { get; set; }

    public string ToUrl(string absoluteUrl)
    {
        return Include == null ? absoluteUrl 
            : absoluteUrl.AddQueryParam("include[]", string.Join(",", Include));
    }
}

[IgnoreDataMember] is used to hide the property being emitted using the default convention

Which when sending the Request DTO:

var response = client.Get(new GetStripeCustomers());

Generates and sends the relative url:

/customers?include[]=total_count

Which has the effect of populating the TotalCount property in the typed StripeCollection<StripeCustomer> response.

Web Framework

Structured Request Binding Errors

Previously type conversion errors would throw a generic RequestBindingException to indicate the Request was malformed. They are now being converted into a structured error so the same error handling logic used to handle field validation errors can also handle request binding exceptions, e.g:

try
{
    var response = client.Get<RequestBinding>("/errorrequestbinding?Int=string");
}
catch (WebServiceException ex)
{
    ex.ResponseStatus.Message //= Unable to bind 'RequestBinding': Input string was not in a correct format.

    var fieldError = ex.GetFieldErrors()[0];
    fieldError.FieldName //= Int
    fieldError.ErrorCode //= SerializationException
    fieldError.Message   //= 'string' is an Invalid value for 'Int'
}

Special thanks to @georgehemmings for his contributions to this feature.

Scalable Server Events

@Nness upgraded our existing Server Events implementation based on manual array re-sizing and custom locks to use ConcurrentDictionary to solve their scalability issues they were having at 25-30k concurrent Server Event connections.

The default synchronous WriteEvent implementation can be overridden which .NET 4.5 applications can take advantage to use asynchronous Write and Flush API's with:

Plugins.Add(new ServerEventsFeature
{
    WriteEvent = (res, frame) =>
    {
        var aspRes = (HttpResponseBase)res.OriginalResponse;
        var bytes = frame.ToUtf8Bytes();
        aspRes.OutputStream.WriteAsync(bytes, 0, bytes.Length)
            .Then(_ => aspRes.OutputStream.FlushAsync());
    }
});

Metadata pages

To avoid repetitive noise in each Metadata Operation Page the common ResposneStatus DTO's were omitted, if you prefer they can now be enabled with:

this.GetPlugin<MetadataFeature>().ShowResponseStatusInMetadataPages = true;

AutoQuery

Querying NULL

You can implicitly query a Column is null by specifying a property with no value, e.g:

/rockstars?DateDied=

Will return all Rockstars where DateDied IS NULL.

Other Changes

  • ISequenceSource changed to use longs
  • Add Support for Fluent Validation's RuleForEach()
  • Use AuthFeature.HtmlLogoutRedirect to specify the browser redirect after logout
  • Change Exception returned by overriding ResolveResponseException() in AppHost

Release Notes History