Spring architecture & package/class structure

I wasn’t happy with the way the packages/classes were distributed in https://github.com/openmrs/openmrs-module-radiology and also how everything (ServiceImpl, DAO interface, DAO hibernate implementation) was just public.

I then stumbled upon this talk about Spring application architecture:

… with an accompanying codebase: https://github.com/olivergierke/whoops-architecture, and I liked it a lot :slight_smile:

So it basically just says that in a layered application with 3-tiers like Presenation/Service/DAO. You could create packages for your domain objects like for example in my case I have the RadiologyReport. Then put the 3-tiers into that package:

package org.openmrs.module.radiology.report

  • RadiologyReport (public domain object)
  • RadiologyReportService (public interface)
  • RadiologyReportServiceImpl (package private default implementation)
  • RadiologyReportDAO (package private interface)
  • HibernateRadiologyReportDAO (package private hibernate DAO implementation)

(leaving the Presentation out, could be in a subpackage called web for example)

I thus only expose the service interface and the domain object but not the rest, since I dont have to go across package boundaries. I thus force other developers to use my service interface and not mess directly with the DAO or the default service implementation.

I then encountered that the https://github.com/openmrs/openmrs-module-emrapi/tree/master/api/src/main/java/org/openmrs/module/emrapi kind of uses this way of structuring their code.

What is your take on this?

It depends, for instance if the categorisation is by functional module and the module has many domain objects, having all of them along with services and DAOs doesn’t seem good. But I suppose it’s a matter of taste.

What do you mean by categorization is by functional module?

Division in slices, according to the video.

But its service and DAOs implementations are public. If they are package-private, will Spring be able to instantiate them?

Yes spring can still instantiate them. Only my domain object and service interface are public, everything else (service impl, dao interface, and dao impl) is package private.

@lluismf when the domain objects are many, they could be divided into sub packages.

@teleivo i have seen a few debates about package by feature vs by layer. Others going for a mixture of the two. My personal take on this is, do what is most relevant for your particular project. :smile:

1 Like

I know, I use this kind of packaging at work (not a Spring app though). In fact, as we have hundreds of entities there are multiple levels of packaging. But we don’t mix entities with business components or DAOs.

can you elaborate why you don’t mix entities with business components or DAOs?

in the radiology modules case its just the simplest solution. least packages, better control of access to the types.

@teleivo i personally do not think that package by feature forces mixing business components, DAO, etc. You can still use the same parent feature package but have DAOs, Domain objects, services, etc in different sub packages. Though if they are very few, mixing them would be the simplest, if it does not hurt your instincts. :smile:

@dkayiwa I know I could still create subpackages but than again I would have to make DAO and DAO implementation public which I dont want.

It was an architectural decision and I was not involved, but I think that the original idea was to run presentation and business layer as separate EARs.

To meet this requirement and avoid errors, the Eclipse workarea is divided by projects (one per layer). Presentation layer project can’t see business layer project (and viceversa). POJOs reside in a common layer visible by the other layers (but itself can’t see any other layer).

As you see, each project is a world :slight_smile:

Replying quite late here: @teleivo, I approve of what you’re suggesting for lots of cases.

(I think I was the one that pushed towards EMR API being organized this way, and looking at the example of https://github.com/openmrs/openmrs-module-emrapi/tree/master/api/src/main/java/org/openmrs/module/emrapi/adt I think it illustrates why it’s not worth the effort of specifically moving the Service, ServiceImpl, etc, into their subpackages that ultimately only contain 1-2 files.)