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.
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. https://yoursite.com and https://api.yoursite.com. 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.