Traditional Web Apps And RESTful APIs

When we are building web applications these days, it is considered a best practice to expose all our functionality as a RESTful API and then consume it ourselves. This usually goes with a rich front-end using heavy javascript, e.g. Angular/Ember/Backbone/React.

But a heavy front-end doesn’t seem like a good default – applications that require the overhead of a conceptually heavy javascript framework are actually not in the majority. The web, although much more complicated, is still not just about single-page applications. Not to mention that if you are writing a statically-typed backend, you would either need a dedicated javascript team (no necessarily a good idea, especially in small companies/startups), or you have to write in that … not-so-pleasant language. And honestly, my browsers are hurting with all that unnecessary javascript everywhere, but that’s a separate story.

The other option for having yourself consume your own RESTful API is to have a “web” module, that calls your “backend” module. Which may be a good idea, especially if you have different teams with different specialties, but the introduction of so much communication overhead for the sake of the separation seems at least something one should think twice before doing. Not to mention that in reality release cycles are usually tied, as you need extra effort to keep the “web” and “backend” in proper sync (“web” not requesting services that the “backend” doesn’t have yet, or the “backend” not providing a modified response model that the “web” doesn’t expect).

As in my defence of monoliths, I’m obviously leaning towards a monolithic application. I won’t repeat the other post, but the idea is that an application can be modular even if it’s run in a single runtime (e.g. a JVM). Have your “web” package, have your “services” package, and these can be developed independently, even as separate (sub-) projects that compile into a single deployable artifact.

So if you want to have a traditional web application – request/response, a little bit of ajax, but no heavy javascript fanciness and no architectural overhead, and you still want to expose your service as a RESTful API, what can you do?

Your web layer – the controllers, working with request parameters coming from form submissions and rendering a response using a template engine – normally communicates with your service layer. So for your web layer, the service layer is just an API. It uses it using method calls inside a JVM. But that’s not the only way that service layer can be used. Frameworks like Spring-MVC, Jersey, etc, allow annotating any method and exposing it as a RESTful service. Normally it is accepted that a service layer is not exposed as a web component, but it can be. So – you consume the service layer API via method calls, and everyone else consumes it via HTTP. The same definitions, the same output, the same security. And you won’t need a separate pass-through layer in order to have a RESTful API.

In theory that sounds good. In practice, the annotations that turn the method into an endpoint may introduce problems – is serialization/deserialization working properly, are the headers properly handled, is authentication correct. And you won’t know that these aren’t working if you are using the methods only inside a single JVM. Yes, you will know they work correctly in terms of business logic, but the RESTful-enabling part may differ.

That’s why you need full coverage with acceptance tests. Something like cucumber/JBehave to test all your exposed endpoints. That way you’ll be sure that both the RESTful aspects, and the business logic work properly. It’s actually something that should be there anyway, so it’s not an overhead.

Another issues is that you may want to deploy your API separately from your main application. and You may want to have just the API running in one cluster, and your application running in another. And that’s no issues – you can simply disable the “web” part with a configuration switch and your application and deploy the very same artifact multiple times.

I have to admit I haven’t tried that approach, but it looks like a simple way that would still cover all the use-cases properly.

Share Button

Leave a Reply

Your email address will not be published. Required fields are marked *