-1

During this weekend I read "Get Your Hands Dirty on Clean Architecture" by Tom Hombergs. I am working on a microservice that was born with Hexagonal Architecture in mind, so I was able to recognize a lot of patterns already; anyway, I am still a bit unsure of the role that a Spring Application would play in such architecture.

My microservice is composed of a Spring Reactive web application exposing a GraphQL interface, a relational database, and a third-party REST API client.

I get that the GraphQL interface itself should map to an input adapter, where the GraphQL resolvers would then call the input port implementations in order to interact with the domain. Since I'm using Spring Boot and DGS Framework to handle GraphQL queries and mutations, the GraphQL adapter module will certainly contain the GraphQL resolvers.

As said, I am not sure what to do exactly with the Spring Boot Application itself, which will basically spin up the HTTP Server, host a health check REST controller and the authentication logic for the GraphQL endpoint, the GraphiQL UI, and the aforementioned health check controller. Currently it is in the same module that contains the GraphQL adapter, but my instinct tells me that it should be kept in a separate module, because of the "compositing" role it has in regard to the various port implementations; also, keeping it merged with the web app with the GraphQL adapter would mean making it aware of the other adapters, because the web app would need to also access them, so it goes against the separation of concerns.

On the other hand, keeping them separated makes me wonder how should I approach the GraphQL adapter tests: currently, I have some tests that make a POST call to the GraphQL server and assert against the content of the response, but since the GraphQL adapter shouldn't know anything about the HTTP layer, I think having to spin up an HTTP test server is leaking unnecessary details about the presence of the HTTP server.

So, to summarize my post: is it correct to have the web app application in a separate module from the GraphQL adapter, or they should live close to each other?

I hope what I wrote makes at least a little sense. Of course, feel free to ask any detail that could be useful to the discussion.

4
  • so it goes against the separation of concerns. why does it matter to you? Forget dogmas... Is there a business motivation that prevents you from implementing one or another solution? Does one approach seem better aligned with your organization's way to work and operate? Do you find one solution to be best for non-technical reasons? Commented May 17, 2023 at 9:57
  • Well... No, I don't think there is. But at this point, putting together the webapp (and its dependencies towards the output port implementations) and the GraphQL interface (so the input implementation) kinda kills all the purpose of having an hexagonal architecture, isn't it? Are you implying that such architecture might not be the best fit for me? However, regardless of my specific use case, I am curious about the answer itself. I guess that having a web application is quite a standard requirement nowadays, so I'm curious to understand how it is implemented. Commented May 17, 2023 at 10:02
  • It's perfectly fine to have everything bundled in the web app (modules or not) or even each interface (rest, graph, sockets, etc) as standalone services. It depends a lot on non-functional requirements. Non-functional requirements are strongly biased by a business or organizational needs. That's why ask you why "separation of concerns" is that stringent for you. As with coupling, we can live with it if no superior motivations dictate the opposite. Commented May 17, 2023 at 10:13
  • Ok, now it's a bit more clear, thank you. However, as I said, I would still like to understand how Hexagonal Architecture deals with this point, regardless of my specific use case. I think that understanding this would lead me to a better understanding of the architecture itself. Commented May 17, 2023 at 10:29

2 Answers 2

2

Hexagonal architecture is just one of possible styles. If an application follows it, it doesn't automatically mean that it is good for its purpose. And if an application doesn't follow this style, it doesn't automatically mean that it is not good.

The idea behind hexagonal architecture is to pay a lot of attention to creating of decoupled components. One expects that there is a core that implements business logic and there are ports/adapters for interaction with other systems.

Usage of Spring Boot does not say anything if your architecture follows hexagonal style or not. Spring Boot is just a platform. It depends on you, how design the application.

Nevertheless, Spring Boot allows to implement hexagonal architecture, if you wish it. Just a few examples:

  • Servlet container is well isolated from the remaining part. Default is Tomcat. But you can use Jetty or Undertow instead of the Tomcat.
  • REST controllers, GraphQL controllers, SOAP services, message queue listeners: If you can call the same logic from a REST controller and from a message queue listener, it means the core logic is well isolated and corresponds to the hexagonal style. If not, e.g. if some business logic is implemented directly in the REST controller and some in the services called from the controller, then the core is not isolated well and it does not follow hexagonal style.
  • Outgoing communication: If you mix business logic with calls of external services, it is not the hexagonal style. But if you put the calls of external services to separate components (e.g. @Service), then you can change implementation details later on, without changing the core. E.g. such service can call an external service using RestTemplate, later on you can change it to use OkHttp.
  • Logging: Spring Boot supports SLF4J out-of-the-box. Application code can use SLF4J (which corresponds to a port in the hexagonal architecture), where as particular implementation is configurable. You can configure logging to write some data to files, to database, to send log data via network to Splunk or other logging system.
  • Authentication: The core (the business logic) knows only that authentication is available via SecurityContextHolder, but it "does not know" how exactly was the user authenticated. You can configure the application to use basic auth, or OAuth2, or other. Depending on that the application binary may contain a few more JARs. Thus, the core is isolated well from particular implementation of authentication. If you use it, you follow hexagonal style.

And so on.

TLDR: Spring Boot is just a platform. It makes it relatively easy to implement hexagonal architecture. But it depends on you, if your architecture is hexagonal or not.

2
  • I think my bias comes from the fact that a SpringApplication (I mean, the actual class annotated with @SpringBootApplication), in a project whose parent is spring-boot-starter-web, has both the Spring features AND the HTTP Server in the same package. After writing my message I realized that this is not the only way, and that probably separating the HTTP Server from the Spring Application and moving it near to the GraphQL Adapter could be a solution for my question. Commented May 17, 2023 at 15:13
  • 3
    @ClaudioMezzasalma: spring-boot-starter-web is a typical starter project. Its purpose it to be a single artifact that one needs for particular purpose, in this case for a web application. And it is normal, that there is a class that knows about classes from different modules, because there should be a place where different modules are "glued" together. Commented May 17, 2023 at 15:26
1

If your question is where to put the main application class (that is annotated with @SpringBootApplication, then the answer is to put it in the main package as you would normally do.

You shouldn't care that this class "knows" that it's a web application etc. It's a concern of the Spring Boot library, not a concern of your code.

Yes, some of Spring Boot will leak into your code (like the @Component annotation or other annotations you're using). But if you try to abstract the Spring Boot framework away completely, you just make your life harder.

Have a look at my example application on GitHub. That's how I would (roughly) organize the code of a hexagonal Spring Boot app (note that my opinions have changed a bit over the last couple years, and I'm about to update that GitHub repo a bit for the second edition of my book, but the gist of it still holds true for me.

3
  • Well, more than the package (I should have mentioned I am using Kotlin, so I cannot really achieve package separation here) I was more concerned about the Maven modules, and with it the dependencies of each module. Should I put the main application in the GraphQL adapter module, I would have polluted that module with a lot of other dependencies (other adapters, persistence library). Commented May 18, 2023 at 6:53
  • @ClaudioMezzasalma the app (which is also a layer) is going to be coupled (polluted) by many dependencies because it's the layer where most of the concreteness is solved. The app layer is the layer sorting out the dependency inversion (dependency graph), so it's likely to be aware of many things (concrete adapters, concrete persistence library, concrete framework, ...) Commented May 18, 2023 at 7:17
  • Yes, this is exactly my point. Since the app needs to sort out dependencies, I think it's not optimal to share this need with the GraphQL adapter. It shouldn't be aware of other dependencies, that's why I think they should be decoupled. Commented May 18, 2023 at 10:16

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.