What magic happens in kotlin - spring-boot

I have kotlin + spring boot app. I done some development in my feature branch committed and returned to dev branch, built app and just tried to start it in intellij idea, but get an error
Error: Main method not found in class com.test.Application, please define the main method as:
public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application
I could swear it worked and moreover it works.
#SpringBootApplication
#EnableScheduling
#EnableConfigurationProperties()
class Application {
}
fun main(args: Array<String>) {
runApplication<Application>(*args)
}
Where i should look for reason of this issue - kotlin, intellij idea?
Thanks

Your main() function is a package-level (AKA ‘top-level’) function, because it's not defined within your Application class (or, more usually for main(), its companion object).
And in Kotlin/JVM, package-level functions are treated as belonging to a special class named for the source file, with a Kt suffix.
So in this case, you should specify the main class as com.test.ApplicationKt.
(The language docs describe this here. This is one of those implementation details that you normally don't need to know; it's only important when specifying your main class, or calling a package-level function from Java.)

Related

kotlin sealed class with Spring #Component

I am relatively new to kotlin but already loving it. In one of our projects, we use kotlin; when I tried to annotate a sealed class with Spring's #Component, the compiler threw the following exception,
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'ShutDownManager' available
The simple shutdown manager class
package com.tes.streamconsumer.stream.processor
#Component
sealed class ShutDownManager(
#Autowired private val applicationContext: ApplicationContext
) {
fun shutDownApplication() {
SpringApplication.exit(applicationContext)
}
}
That is Autowired in another class,
package com.tes.streamconsumer.stream.processor
#Component
class AccountFacade(
#Autowired private val shutDownManager: ShutDownManager
) {
}
From the Kotlin documentation on sealed class, I understand this is useful to have restricted class hierarchies that provide more control over inheritance, so my questions below,
Is the sealed class not meant to be used with spring injection
or the ApplicationContext not ready hence the bean was not created?
Please shed light on what I miss here; thanks.
Your problem is nothing to do with the sealed class but elsewhere. Typically this kind of error occurs because Spring is not scanning your code looking for Beans in the way you expect.
You have correctly annotated your ShutDownManager class with #Component but you don't give enough information on your package structure.
This is the right kind of package structure for a Spring project:
com.mydomain.myapp
.facades
.AccountFacade.kt
.managers
.ShutDownManager.kt
.MyApp.kt
What is important is the Spring entrypoint class is higher than all the packages where you declare your Beans. The default behaviour of Spring is to Scan the packages below looking for Components/Services/etc. (You can override the behaviour to scan packages, etc explicitly, but my general preference is to locate the entry point for your application at the top of the tree on its own so it is easy to find in the tree structure and then everything beneath.)
One other word of caution is that in Java the package structure is intrinsically linked to the file system folder structure - you must keep them matched. There is no such restriction in Kotlin. I recommend not making use of this, since many Java devs will use the folder structure and never notice the package declaration differs; this could also be the source of Spring not finding your Beans.
Use of sealed classes/interfaces
I guess you might be thinking of using sealed to protect your ShutDownManager from being subclassed or overriden, but actually by default Kotlin makes all classes final. (You have to explicitly permit subclassing using the open keyword.)
sealed classes have some specific benefits in other places - most often when you are creating data objects, say Apple and Pear that implement/extend from Fruit. You can then write code that knows that there can only be two fruits if you had said sealed class Fruit. In Kotlin there is a when statement that's like Java's switch...case, and the compiler would know there is no need for an else if you were using a sealed Fruit class. See this article:
https://commonsware.com/Kotlin/pages/chap-sealed-002.html

Spring boot : configuration inheritance

I have
package com.parent.spring;
public abstract class ParentConfig {
#Bean
public String bParent() {
return "parent bean";
}
then
package com.child.spring;
public class ChildConfig extends ParentConfig {
#Bean
public String bChild() {
return "child bean";
}
}
and here's how I am starting my spring boot app
#SpringBootApplication
#ComponentScan(basePackages = { "com.child.spring","com.parent.spring" })
public class MyMain {
public static void main(String args[]) throws Exception {
SpringApplication.run(MyMain.class, args);
}
}
I want to load beans from child config first and the from parent config. However, opposite is happening. Don't want to use depends on option as this is just an example, in reality I have lot of beans in child and parent config. Also, I have bunch of other configuration classes in parent package so I don't want to remove that from component scan. Any nicer solution on this ?
I want to load beans from child config first and the from parent
config.
You want to explain to the framework how to do its work ?
Spring Configurations and more generally Spring beans are loaded and added in the context in a order that Spring considers the right to satisfy all dependencies requirements.
Besides, configuration inheritance is not documented as a way to achieve such a thing.
Specifying explicitly the order for specific beans is possible but it should be the exception and not the norm while you seem want to do that exception the norm.
Could you please explain more your use case so that we could provide you the best solution we can :) ?
In general its a wrong approach to treat #Configuration files as regular java classes and use all the power of java as a language for the code in this files. You mention inheritance, how about complicated if-conditions, loops, recursion, anyone? :) My point is that you don't really want to end up with complicated code in configuration and to debug it.
Now regarding the inheritance itself. This is not a good idea, because given the fact that its not a regular java class combined with the understanding of how exactly spring uses these configuration files, you'll understand that configuration gives nothing to you here.
Think about configurations as a place where you state which beans should be loaded. Spring will take care of the rest. I do understand that you have some use case in mind, but it simply doesn't fit Spring approach.
As for your statement:
I want to load beans from child config first and the from parent config.
Could you please explain why do you need this?
When spring loads it scans all the configurations first but doesn't create beans (not yet). Instead it "translates" the information found in these #Configuration classes to a "metadata" (this is called "Bean Definitions" in terms of spring). All the bean definitions from all the configurations....
Only after that Spring starts beans instantiation (it also knows by this time what bean should be created first, for example if you have something like):
class A {
private B b;
public A(B b) {this.b = b;}
}
class B {
....
}
Then its obvious that Spring should create Bean "B" first.

How to use #Autowired correctly in spring boot standalone app

I've learned a lot recently about Spring and one thing i think i might be misunderstanding is the #Autowired annotation, especially when using it in constructors. You see, the app i'm developing is a service so basically EVERYTHING is initialized within a constructor. The only actual user-driven events that happen are buttons that restart certain modules of the service. This is my main method :
ConfigurableApplicationContext ctx = new SpringApplicationBuilder(MDHIS_Service.class)
.headless(false).web(false).run(args);
java.awt.EventQueue.invokeLater(() ->
{
MDHIS_Service frame = ctx.getBean(MDHIS_Service.class);
frame.setSize(1024, 768);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
This is the constructor of my main class, where basically everything happens. I have omitted the calls to the methods initializing each module to shorten it :
#Autowired
public MDHIS_Service(GlobalParamService globalParamService, LogEntryService logentryService, InterfaceService interfaceService,
ConnectionService connectionService, OutboundMessageService outboundMessageService, OutboundMessageHistoryService outboundMessageHistoryService,
InboundMessageService inboundMessageService, FacilityService facilityService, ModuleStatusService moduleStatusService,
SequenceService sequenceService)
{
this.globalParamService = globalParamService;
this.logEntryService = logentryService;
this.interfaceService = interfaceService;
this.connectionService = connectionService;
this.outboundMessageService = outboundMessageService;
this.outboundMessageHistoryService = outboundMessageHistoryService;
this.inboundMessageService = inboundMessageService;
this.facilityService = facilityService;
this.moduleStatusService = moduleStatusService;
this.sequenceService = sequenceService;
}
My main class has a private final global variable for each service. Each module is a separate thread and i'm finding myself having to pass those variables to the constructor of each module which in term stores them into it own private final variables. The way i'm doing things right now #Autowired is pretty much useless since i'm having to pass the instance around. Is there a way to better use #Autowired? This service is used as the backend for a large web app and i find myself making much better use of the annotation in there. I did a lot of research on this topic and i did try the #PostContruct annotation but all i ever got was null services.
Any help would be appreciated.
Thanks!
I figured out my problem, and it was a pretty dumb one. First off, i had not annotated my main class with #Component so Spring never bothered to inject the dependencies in it. Secondly, I did not realize that a method annotated with #PostContruct would run by itself after the constructor runs WITHOUT NEEDING TO EXPLICITELY BE CALLED!
I moved all my initialization code to an init method annotated with #PostConstruct and annotated my main class with #Component, everything is working now!
You typicall don't have to use a constructor + #Autorwired, you can directly use autowired on fields and spring would fill the dependencies for you:
#Component
public class MDHIS_Service {
#Autowired
private GlobalParamService globalParamService;
}
What is important to understand is that for spring to work, you must let it create the objects for you, and not calling the constructors explicitely. It would then fill the dependencies as needed. This is done by declaring the service as a component (for example with the #Component annotation) and never create the service yourself but getting them from dependency injection.
The first object you start with has to have been created by spring and returned by the application context.
What you gain in exchange is that you don't have to forwared everything explicitely. A sub-sub-sub service quite distant from the root of the application can depend on anything it has visibility without you having to forward the reference all the way.
I would advise to take a look a the spring reference documentation, it quite detailled and complete:
https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#spring-core
Edit: I'll try to clarify a bit with an example... What do the init code of the various service actually does ?
Maybe it set the dependencies. Then just autowire them:
#Component
MySubService {
#Autowired MySubSubService mySubSubService;
}
Maybe it does some more thing than setting fields so you can add on top an init method that do it and this init method can eventually call the other services.
#Component
MySubService {
#Autowired MySubSubService mySubSubService;
#PostConstruct
public void init() {
//Init code that may use mySubSubService.
}
}
You don't have to declare a constructor and forward dependencies yourself, sprint does it for you.
The only case where you'd have problem is if finally you need some parameters that are not dependency to the init method. But even in that case you could do it from you main code. That's actually what you did with the main service calling the various setters rather than messing with the constructor to set theses values.

Java Configuration vs Component Scan Annotations

Java configuration allows us to manage bean creation within a configuration file. Annotated #Component, #Service classes used with component scanning does the same. However, I'm concerned about using these two mechanisms at the same time.
Should Java configuration and annotated component scans be avoided in the same project? I ask because the result is unclear in the following scenario:
#Configuration
public class MyConfig {
#Bean
public Foo foo() {
return new Foo(500);
}
}
...
#Component
public class Foo {
private int value;
public Foo() {
}
public Foo(int value) {
this.value = value;
}
}
...
public class Consumer {
#Autowired
Foo foo;
...
}
So, in the above situation, will the Consumer get a Foo instance with a 500 value or 0 value? I've tested locally and it appears that the Java configured Foo (with value 500) is created consistently. However, I'm concerned that my testing isn't thorough enough to be conclusive.
What is the real answer? Using both Java config and component scanning on #Component beans of the same type seems like a bad thing.
I think your concern is more like raised by the following use case:
You have a custom spring-starter-library that have its own #Configuration classes and #Bean definitions, BUT if you have #Component/#Service in this library, you will need to explicitly #ComponentScan these packages from your service, since the default #ComponentScan (see #SpringBootApplication) will perform component scanning from the main class, to all sub-packages of your app, BUT not the packages inside the external library. For that purpose, you only need to have #Bean definitions in your external library, and to inject these external configurations via #EnableSomething annotation used on your app's main class (using #Import(YourConfigurationAnnotatedClass.class) OR via using spring.factories in case you always need the external configuration to be used/injected.
Of course, you CAN have #Components in this library, but the explicit usage of #ComponentScan annotation may lead to unintended behaviour in some cases, so I would recommend to avoid that.
So, to answer your question -> You can have both approaches of defining beans, only if they're inside your app, but bean definitions outside your app (e.g. library) should be explicitly defined with #Bean inside a #Configuration class.
It is perfectly valid to have Java configuration and annotated component scans in the same project because they server different purposes.
#Component (#Service,#Repository etc) are used to auto-detect and auto-configure beans.
#Bean annotation is used to explicitly declare a single bean, instead of letting Spring do it automatically.
You can do the following with #Bean. But, this is not possible with #Component
#Bean
public MyService myService(boolean someCondition) {
if(someCondition) {
return new MyServiceImpl1();
}else{
return new MyServiceImpl2();
}
}
Haven't really faced a situation where both Java config and component scanning on the bean of the same type were required.
As per the spring documentation,
To declare a bean, simply annotate a method with the #Bean annotation.
When JavaConfig encounters such a method, it will execute that method
and register the return value as a bean within a BeanFactory. By
default, the bean name will be the same as the method name
So, As per this, it is returning the correct Foo (with value 500).
In general, there is nothing wrong with component scanning and explicit bean definitions in the same application context. I tend to use component scanning where possible, and create the few beans that need more setup with #Bean methods.
There is no upside to include classes in the component scan when you create beans of their type explicitly. Component scanning can easily be targeted at certain classes and packages. If you design your packages accordingly, you can component scan only the packages without "special" bean classes (or else use more advanced filters on scanning).
In a quick look I didn't find any clear information about bean definition precedence in such a case. Typically there is a deterministic and fairly stable order in which these are processed, but if it is not documented it maybe could change in some future Spring version.

how to use spring scala to decouple?

I like to add Spring to my Scala projects for educational purposes. But I do not understand the advantage of Spring Scala to decouple components.
I have created a simple configuration:
import org.springframework.scala.context.function.FunctionalConfiguration
class Configuration extends FunctionalConfiguration {
bean() {
new Service()
}
}
and a simple service:
class Service {
def method = "Bonjour tout le monde!"
}
and then an application which uses both:
import org.springframework.scala.context.function.FunctionalConfigApplicationContext
object Application extends App {
implicit val context = FunctionalConfigApplicationContext(classOf[Configuration])
val service = context.getBean(classOf[Service])
println(service.method)
}
This is just my interpretation and implementation of the Spring Scala examples.
My application still has knowledge of the Service class. I could just write:
val service = new Service() // instead of asking for a Bean which has classname Service
println(service.method)
with the same effect.
Am I missing something?
This does decouple your use of the Service from the instantiation of it. E.g. if in the future Service changes to depend on some other InnerService, or has some initialization that can't be done in the constructor for some reason but needs to happen in a method call before it's used (.connectToDatabase() or some such), or if you wanted to replace the Service with a mock one for testing, then you can do this without changing these two lines of code:
val service = context.getBean(classOf[Service])
println(service.method)
If you program to an interface rather than implementation, e.g.
trait IService {
def method: String
}
class Service extends IService...
val service = context.getBean(classOf[IService])
then you also make it easy to swap out the Service for a different implementation, though given the extra lines of code I probably wouldn't bother doing this until I actually had more than one implementation.
I'm not sure that Spring carries its own weight (it's a very large and complex library), particularly in Scala with its more concise constructor syntax. But whether you use Spring or not, it's worth separating the construction of your dependencies and "wiring up" of your application from their actual use. IMO a class Foo that uses Service should accept it, explicitly via its constructor, class Foo(service: Service), and leave the construction/initialization of Service to a class/or function dedicated to that.

Resources