Spring directory structure with interfaces (best practices) - java

I'm currently writing my first Spring application (Spring boot + hibernate). I checked the best practices directory structure on their documentation here. It makes sense.
Question 1:
I have an interface (or Abstract class) that a few subclasses extend, and so I only need a #Repository for the parent class. I've decided to do it this way:
com
+- example
+- myapplication
+- Application.java
|
+- message
| +- AbstractMessage.java
| +- IMessageRepository.java
| +- MessageRepositoryImpl.java
+- messageTypeA
| +- messageTypeA.java
| +- messageTypeAService.java
+- messageTypeB
| +- messageTypeB.java
| +- messageTypeBService.java
Question 2:
Now I have a new entity to save called Group. So what I could do is add a Group directory on the same level as Message. However, this Group is actually a part of Message (like, logically), so it would actually make sense if it was part of the same message directory (the only reason we are saving them as different entities is because it makes more sense to derive analytics that way). Furthermore I'm even using the same MessageRepository to save it (I just added a second method in the interface like so:)
public interface MessageRepository {
void insert(AbstractMessage message);
void insert(AbstractMessage message, AbstractGroup group);
}
Would something like the following be good? Or should every entity have its own package? Am I overthinking this?
com
+- example
+- myapplication
+- Application.java
|
+- message
| +- AbstractMessage.java
| +- IMessageRepository.java
| +- MessageRepositoryImpl.java
| +- messageTypeA
| +- messageTypeA.java
| +- messageTypeAService.java
| +- messageTypeB
| +- messageTypeB.java
| +- messageTypeBService.java
|
+- group
+- AbstractGroup.java
+- GroupTypeX.java // same service as message, just different entity
+- GroupTypeY.java // same service as message, just different entity

That's more an opinion-based thing, but I'd like to give you a couple suggestions.
First of all, naming.
The I prefix on interfaces is an "ancient" technique from IBM to recognize them. Please, don't do that, it's reduntant, it doesn't make sense in a fresh environment. What's an I-MessageRepository?!
You'll find this kind of naming convention mostly on Eclipse RCP projects, or any product by IBM.
Then the implementation name. Don't use the Impl suffix, it does not say anything to the person who is reading or editing your code.
Give it a name which says what its purpose or domain scope is.
ActiveMQMessageRepository
FileMessageRepository
TcpMessageRepository
Second, Repositories.
Repositories should manage a single type of object, not more than one. Use Services to coordinate multiple Repositories. This will make it easier for everyone to debug, and it will decouple a lot of code.
Third, packages.
Try to always have a flat package structure. A flat structure is easier to maintain, easier to look at, easier to understand. Don't create dozens of sub-packages such as
- messages
- services
MessageService
- implementations
...
- repositories
MessageRepository
- abstract
AbstractMessageRepository
- implementations
TextMessageRepository
- exceptions
- runtime
- checked
UnsupportedMessageException
Horrible and useless. And you cannot leverage package visibility.
So keep messages and groups on separate packages, and give them their own Repository.
Expose interfaces from packages, not concrete implementations. (when possible)

I agree with #LppEdd answer above. Just one question what do you mean when you say
(the only reason we are saving them as different entities is because it makes more sense to derive analytics that way).

Related

What is the recommended project structure for spring boot rest projects? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed last year.
The community reviewed whether to reopen this question last year and left it closed:
Original close reason(s) were not resolved
Improve this question
I'm a beginner with spring boot. I'm involved in the beginning of a project where we would build rest services using spring boot. Could you please advise the recommended directory structure to follow when building a project that will just expose rest services?
From the docs:, this is the recommended way
The following listing shows a typical layout:
com
+- example
+- myapplication
+- Application.java
+- customer
+- Customer.java
+- CustomerController.java
+- CustomerService.java
+- CustomerRepository.java
+- order
+- order.java
+- OrderController.java
+- OrderService.java
+- OrderRepository. java
The Application. java file would declare the main method, along with the basic SpringBootApplication as follows:
package com.example.myapplication;
import org. springframework.boot.springApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication public class Application {
public static void main(string[] args)
{
springApplication.run(Application. class, args);
}
}
config - class which will read from property files
cache - caching mechanism class files
constants - constant defined class
controller - controller class
exception - exception class
model - pojos classes will be present
security - security classes
service - Impl classes
util - utility classes
validation - validators classes
bootloader - main class
You do not need to do anything special to start. Start with a normal java project, either maven or gradle or IDE project layout with starter dependency.
You need just one main class, as per guide here and rest...
There is no constrained package structure. Actual structure will be driven by your requirement/whim and the directory structure is laid by build-tool / IDE
You can follow same structure that you might be following for a Spring MVC application.
You can follow either way
A project is divided into layers:
for example: DDD style
Service layer : service package contains service classes
DAO/REPO layer : dao package containing dao classes
Entity layers
or
any layer structure suitable to your problem for which you are writing problem.
A project divided into modules or functionalities or features and A module is divided into layers like above
I prefer the second, because it follows Business context. Think in terms of concepts.
What you do is dependent upon how you see the project. It is your code organization skills.
Though this question has an accepted answer, still I would like to share my project structure for RESTful services.
src/main/java
+- com
+- example
+- Application.java
+- ApplicationConstants.java
+- configuration
| +- ApplicationConfiguration.java
+- controller
| +- ApplicationController.java
+- dao
| +- impl
| | +- ApplicationDaoImpl.java
| +- ApplicationDao.java
+- dto
| +- ApplicationDto.java
+- service
| +- impl
| | +- ApplicationServiceImpl.java
| +- ApplicationService.java
+- util
| +- ApplicationUtils.java
+- validation
| +- impl
| | +- ApplicationValidationImpl.java
| +- ApplicationValidation.java
DAO = Data Access Object.
DTO = Data Transfer Object.
Use Link-1 to generate a project. this a basic project for learning. you can understand the folder structure.
Use Link-2 for creating a basic Spring boot project.
1: http://start.spring.io/
2: https://projects.spring.io/spring-boot/
Create a gradle/maven project Automatically src/main/java and src/main/test will be created. create controller/service/Repository package and start writing the code.
-src/main/java(source folder)
---com.package.service(package)
---ServiceClass(Class)
---com.package.controller(package)
---ControllerClass(Class)
Please use Spring Tool Suite (Eclipse-based development environment that is customized for developing Spring applications). Create a Spring Starter Project, it will create the directory structure for you with the spring boot maven dependencies.

Identify module at runtime

I have a multimodule maven project. One module has several dependencies on other modules in the maven project. I'd like to inspect which top-level module each class is from at run time - is there any way to do this with reflection?
For Example:
com.company:running-module:jar:1.0.0
+- com.company:top-level-module-1:jar:1.0.0:compile
| \- com.company:low-level-module-1:jar:1.0.0:compile
| \- ClassOfInterest.java
+- com.company:top-level-module-2:jar:1.0.0:compile
| \- com.company:low-level-module-1:jar:1.0.0:compile
| \- ClassOfInterest.java
\- com.company:top-level-module-3:jar:1.0.0:compile
\- com.company:low-level-module-2:jar:1.0.0:compile
\- OtherClassOfInterest.java
Inspecting ClassOfInterest would return top-level-module-1 and top-level-module-2 while inspecting OtherClassOfInterest would return `top-level-module-3.
If there is a way to do it, it would be very hacky.
Modify each module to have different top level package and then you can easily do it with reflection by inspecting full class name.

Import package into other module of the same maven project

I've got a maven parent project that has two child modules (spring ws archetypes) each one is intend to be deployed in its own application server. One of the modules exposes a ws endpoint that is used by a ws client in the other module.
My problem is that i will have the java objects generated by jaxb and xsd in both modules, unless i find the way to share this set of classes without replicating it.
Is there any way to import an specific package from one module to the other? Is there other more appropriate way to deal with this problem?
Cheers!
create a ws-api maven module that only contains the api classes interfaces.
create a ws-impl that depends on the ws-api, because it implements it.
create the client module with the ws-api module as it's dependency, because it uses it.
Then you have the following structure, you can reuse the api clases and you have a clear api:
parent-pom
+- ws-api
+- ws-impl
+- client
The module dependencies will be
+------------+ uses +------------+
| client | --------> | ws-api |
+------------+ +------------+
^
| implements
|
+------------+
| ws-impl |
+------------+
In this setup the jaxb objects have to be generated in the ws-api module.
For a detailed explanation of why to separate the api and implementation take a look at my blog
http://www.link-intersystems.com/blog/2012/02/26/separation-of-api-and-implementation/

Unit tests must locate in the same package?

A JUnit book says " protected method ... this is one reason the test classes are located in the same package as the classes they are testing"
Can someone share their experience on how to organize the unit tests and integration tests (package/directory wise)?
I prefer the maven directory layout. It helps you separate the test sources and test resources from your application sources in a nice way and still allow them to be part of the same package.
I use this for both maven and ant based projects.
project
|
+- src
|
+- main
| |
| +- java // com.company.packge (sources)
| +- resources
|
+- test
|
+- java // com.company.package (tests)
+- resources
in my build process, the source directories are
java/src
java/test/unit
java/test/integration
The test and the source code are in different paths, but the packages are the same
java/src/com/mypackage/domain/Foo.java
java/test/unit/com/mypackage/domain/FooTest.java
java/test/integration/com/mypackage/domain/FooTest.java

Hibernate: What am I missing? Can't find #Id, instead #Index

Every example I have found uses #Id, but when I try to write my code, many of the annotations that I'm used to are gone, there are annotatoins like #Index, and the #Entity parameters have changed. I've looked through the Hibernate documentation, and can't find anything talking about changing all of their annotations, so am I looking at a bogus version?
Even #Column() with a name is gone, this is extremely confusing, I'm using Hibernate 3, but I find it hard to believe they went through and broke EVERY annotation that they used to support.
I downloaded the most recent version of Hibernate3.jar, that's all I've included, looking through the JAR I see the annotations packages
import org.hibernate.annotations.Entity;
import org.hibernate.annotations.Table;
I think a wrongly defined class path on your side is more likely than a bogus version. And without more details about the version of Hibernate you're using, the JARs you have on the class path, I don't know what to add.
Update: I'd suggest to use JPA annotations over Hibernate annotations. Here are the dependencies I'm using with the latest version of Hibernate Entity Manager:
org.hibernate:hibernate-entitymanager:jar:3.5.3-Final:compile
+- org.hibernate:hibernate-core:jar:3.5.3-Final:compile
| +- antlr:antlr:jar:2.7.6:compile
| +- commons-collections:commons-collections:jar:3.2:compile
| +- dom4j:dom4j:jar:1.6.1:compile
| | \- xml-apis:xml-apis:jar:1.0.b2:compile
| \- javax.transaction:jta:jar:1.1:compile
+- org.hibernate:hibernate-annotations:jar:3.5.3-Final:compile
| \- org.hibernate:hibernate-commons-annotations:jar:3.2.0.Final:compile
+- cglib:cglib:jar:2.2:compile
| \- asm:asm:jar:3.1:compile
+- javassist:javassist:jar:3.9.0.GA:compile
\- org.hibernate.javax.persistence:hibernate-jpa-2.0-api:jar:1.0.0.Final:compile
No, the annotations haven't changed.
It's hard to us for know if you are looking at a bogus version without knowing what is on your classpath.
Are you sure that hibernate-annotations is on your classpath? As well as the JAR containing the javax.persistence classes (such as hibernate-jpa-2.0-api-1.0.0.Final.jar)?

Categories