Question

I'm facing a design problem with Spring's profile and Maven multimodule project from which i'm building a product, as a web as application that can be customized for differents clients. For this i need quite some organization of my code, this is why i'm seaking advises on how to organises my profiles around my code.

At the moment i'm only using 2 profiles : dev/prod for the whole application. Thoses profiles are both maven profiles and spring profiles. Spring profile is in the web.xml of my web archive which come from maven filtering.

Having only this is a bit annoying when i want to easily switch some classes from others module that rely on some external hardware. Of course i can just add a new profile out of nowhere just to fix this problem.

However i'm searching for a more generic way to handle that, I don't want to end in a profile's soup that are just created because "I need it at that time". Should i create a dev-xxx/prod-xxx profile for each module, or is there better best-practices about it ?


Here are some information about how my project is currently organized, this will give you an idea of what i have currently. But it's not necessary to take this in account in your answer

My full stack for the server : PostgreSQL, Hibernate, JPA, Spring+Spring-Security, CXF (provide JAX-RS implementation and many features as a FIQL search engine), WebSockets, Jackson (json serializer)

Here is how my modules are currently organized, i'm not necesseraly searching an answer that match precisely what i have, but it gives you an idea :

  • Core : contains at the moment all Entities, Business services and rights management. I don't use DTO Objects so all annotation from JPA/Jackson are on the entities (36 tables in database).
  • Rest-Common : Contains some default configurations (jackson mapper, jackson jax-rs provider).
  • RestCore : expose all services to the web world, provide a search service that relies on CXF JAX-RS Search module. URL are protected with spring-security according to the simple rights, further check are done in Business Service.
  • RestReader : expose a set of differents URL for synchronization with a mobile reader. Those are not made to be used by a browser.
  • 2 others independants modules that only implements their technical part.

Note : i know that i can have some intermediary profile of integration environment and so on, they're planned, but i'm doing run of 2-3 weeks for each functionnalities that aren't really specified or designed before hand, so i have currently very few time to clean my full build process, to go for a complete analysis and design and so on. So i may be interested in some answers for the future that i won't be able to implements at the moment.

Was it helpful?

Solution

I would not recommend to put multiple build targets in single Maven project and perform the app customization during build via Spring profiles. This solution is hard to support, because it has reduced visibility of the functionality belonging to specific application/execution context.

Plugin architecture would be better choice here, because it clearly separates the common code from the customer specifics. How can you do that?

Project structure

  project
    core
      pom.xml
    feature1
      pom.xml
    feature2
      pom.xml
    app1
      pom.xml
    app2
      pom.xml

Here you have common functionality in core module and two apps for different customers, that include the core and some of the features as dependencies. "mvn integration-test" of the root project compiles the core, the features and the source code of apps and runs tests, but does not assembly the apps. You can assembly the specific app by building its module.

Application architecture

The core module is an app that can run itself - it contains all necessary infrastructure and minimal functionality. It provides optional interfaces for plugins and configuration API, which allow customization per customer.

Every feature module from above example is a plugin, extending some of the core interfaces. You may use OSGi, but the simplest solution will be to use runtime discovery of Spring application context configurations (you can use web fragments from Servlet 3.0 or let your default configuration include all files from classpath located in, say, '/META-INF/my-spring-plugins'). There you can put all additional configuration and define plugin beans. Let's say for some customer you need a feature A, accessible via REST API as an action on some entity. You can define a component, that will collect list of actions from beans implementing IActionProvider interface. In feature A plugin you implement this interface and return the action definition for this feature.

The app module is a plugin too: it can extend the interfaces that control application branding, database configuration, enterprise integration configuration etc.

OTHER TIPS

If possible create a linked profile between both, allowing you the power to instantly edit/compare/control files on both dev and prod. That is my suggestion, but if anyone else comes along with better experience than me, I would take it from them.

Licensed under: CC-BY-SA with attribution
scroll top