Why can't #Value be resolved in this dependency module? - java

I have a Spring Boot project where project structure looks like below
example(artifactId = example)
+- demo(artifactId = demo)
| +- src
| | +-main
| | +-java
| | +-com
| | +-example
| | +-DemoService
| | +-resources
| | +-application.properties
| +- pom.xml
+- demo2(artifactId = demo2)
| +- src
| | +-main
| | +-java
| | +-resources
| | +-application.properties
| +- pom.xml
+-pom.xml
In this project "demo2" is the dependency of "demo". The "example" module is the parent of both demo and demo2. The
The problem is that when I set the property(site.password=password) in application.properties of demo, I can't resolve it in demo module like this
#Service
public class DemoService {
#Value("${site.password}")
private String password;
}
But if I set it to the application.properties in demo2, it can be solved in the DemoService in demo module.
Thanks in advance!
To clarify:
Demo2 is the main class.

You have the same classpath resource (classpath:application.properties) on both jars, only one will be visible. Usually, configuration should not be packaged in a jar. It should be specified in the package with main method (demo2 in your case).
You can also specify some default values for #Value annotations like: #Value("${site.password:mypassword}") Details
If you still want to include properties in a jar, try putting it in a unique directory like: src/main/resources/com/example/demo.properties and include it in demo2 via spring.config.location.

Application properties packaged inside your jar takes precedence, more details can be found there https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
But you can also set which properties file to use like this
--spring.config.location=classpath:/mydefault.properties

Related

How to put custom Gradle plugins on an another projects build classpath?

I have a published gradle plugin which looks something like this:
|__root
| |
| |
| |__java
| | |__SomeJavaClass.java
| | |__SomeJavaClass2.java
| |
| |__kotlin
| |__MyPluginClass.kts
| |__MyTaskClass.kts
| |__Utils.kts
I would like to include this plugin as a project in my multi project build instead of publishing it to a repo for easier developement.
This plugin has 3 Kotlin files Project A is using. MyPluginClass.kts has my own plugin class, MyTaskClass.kts has my own task class and Utils.kts contains only kotlin functions. The java classes are used in MyPlugin and MyTask.
It is being put on Project A's build.gradle.kts classpath as
classpath("com.my:custom.plugin:version")
A very simplified project structure I would like to achieve:
root
|
|__Project A
| |
| |__build.gradle.kts
| |__x.gradle.kts
| |__y.gradle.kts
| |__settings.gradle
|
|__Project build-logic
| |
| |__build.gradle.kts
| |
| |__java
| | |__SomeJavaClass.java
| | |__SomeJavaClass2.java
| |
| |__kotlin
| |__MyPluginClass.gradle.kts
| |__MyTaskClass.gradle.kts
| |__Utils.gradle.kts
I'm trying to create plugins from those kotlin files and include them in my main build because i need them precompiled, but i cant seem to find a way to put them on Project A's classpath when build.gradle is running there. Is it even possible? what would be the proper solution?
I'm using gradle 7.3
You can combine multiple, independent, Gradle projects using composite builds. The same is also true for Gradle plugins.
Including a Gradle plugin from another directory is documented in the Testing Gradle plugins section.
So if you have a shared-build-logic project that provides a Gradle plugin with an ID my.shared-build-logic, and you want to use that in project-a.
my-projects/
├── shared-build-logic/
│ ├── src/
│ │ └── ...
│ ├── build.gradle.kts
│ └── settings.gradle.kts
└── project-a/
├── src/
│ └── ...
├── build.gradle.kts
└── settings.gradle.kts
Then you need to include shared-build-logic in your project-a Gradle settings file.
// my-projects/project-a/settings.gradle.kts
rootProject.name = "project-a"
pluginManagement {
includeBuild("../shared-build-logic")
}
Now, so long as shared-build-logic correctly provides a Gradle plugin, in project-a you can reference that plugin.
// my-projects/project-a/settings.gradle.kts
plugins {
id("my.shared-build-logic")
}
Finnaly figured out. I didn't create plugins from build-logic, left them as kotlin files. Since it is a separate gradle project, i can just build the project and point project A's classpath to the produced jar file like
buildscript {
dependencies {
classpath(files("path.to.the.jar"))
}
}
this way i can access methods and the MyTask from Project A.
The other issue was that i wanted to apply MyPlugin like
plugins{
id("my-plugin-name")
}
which wasnt working, i guess because it is a class. But now since i had the whole project jar on my build classpath, i can do this:
apply<my-plugin-name>()

Spring directory structure with interfaces (best practices)

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).

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.

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

Categories