how to strart a backend java project using spring? - java

I am starting a spring boot java project. I know I should not to code in the main method and the principal class.
Is this a bad way?:
#SpringBootApplication
public class CesckproApplication implements CommandLineRunner{
#Autowired
private ProcesoPrincipal pp;
public static void main(String[] args) throws Exception {
SpringApplication.run(CanalCorSdqsApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
pp.consulta();
// mycode here....
}
}
There is an other way to execute the code in other classes without touch the main class? i saw some like:
#SpringBootApplication
public class CanalCorSdqsApplication{
#Autowired
private ProcesoPrincipal pp;
public static void main(String[] args) throws Exception {
SpringApplication.run(CanalCorSdqsApplication.class, args);
}
}
And:
#Component
public class ProcesoPrincipal implements CommandLineRunner {
#Override
public void run(String... args) throws Exception {
consulta();
}
public void consulta(){
// my code here
}
}
There is an other way to do it? and what your expertice say about? (some time many of docs and tutrorial use to code in for example MAIN method cus it is just playful not a real aplication when you dont use the main to code all).

If you really want to understand Spring-boot, well you are lucky. There are brilliant sources of information with plenty of examples to go over in https://spring.io/guides and https://www.baeldung.com/spring-boot
Don't take shortcuts to learning; Fail, build, learn and repeat.
These questions you ask:
How to start a backend project?
Is this a bad way?
Is there any other way to execute code, if not in Main?
All of the will have an answer within a couple of tutorials, but if you still do not know which one to pick, go with this one: https://www.baeldung.com/spring-boot-start

Related

How can I control whether JUnit creates an instance of the class whose behaviour is being tested?

I have noticed that JUnit implicitly creates an instance of my test class. I have added my own call to the constructor and this does not prevent the creation of the instance by JUnit; the net result is two instances are created, as shown by the console output below.
I find this puzzling. Why is this taking place, and how can I control/prevent the creation of the instance by JUnit? A google search "junit implicit object creation" reveals nothing, but I was able to see where the constructor is invoked by debugging the test. What I don't understand is why this is taking place, when we have a place to do it ourselves, and how to prevent it from taking place. I am using JUnit 4 in eclipse photon.
Thanks.
public class MainTest extends Main {
static Main m;
#BeforeClass
public static void setUpBeforeClass() throws Exception {
System.out.println("setUpBeforeClass");
m = new Main();
}
#AfterClass
public static void tearDownAfterClass() throws Exception {
System.out.println("tearDownAfterClass");
}
#Before
public void setUp() throws Exception {
System.out.println("setup");
}
#After
public void tearDown() throws Exception {
System.out.println("tearDown");
}
#Test
public void testAdd() {
assertEquals(8,m.add(3,5));
}
}
Console output:
setUpBeforeClass
Main()
Main()
setup
tearDown
tearDownAfterClass
Your testcase extends the class Main which means the constructor is called upon creation of both the MainTest class and the explicit call of new Main()
remove the extends Main and you'll be good

SpringBoot Application with seperate CommandLineRunner that shouldnt run when application starts

I have a springboot application in the form
src/main/java/example
- Application.java
- JobConfiguration.java
scheduler
- Job1.java
- Job1Runner.java
- Job2.java
- Job2Runner.java
I like to be able to run my jobs on demand locally so I create a seperate Runner class for every job (e.g JobRunner.java) but currently when I run my Application class it also runs my Job1Runner class because it extends CommandLineRunner. Is there a way I can keep my runners seperate? (so the Application class doesnt run them, and the JobRunners dont run each other etc)
Application
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
JobConfiguration
#Configuration
#EnableScheduling
public class JobConfiguration implements SchedulingConfigurer {
#Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
// Register jobs
}
}
Example JobRunner
#SpringBootApplication(scanBasePackages = "com.example")
public class JobXRunner implements CommandLineRunner { // Where X is my job index
#Autowired
private final JobX job;
#Override
public void run(String... args) throws Exception {
job.run();
}
public static void main(String[] args) throws Exception {
SpringApplication.run(JobXRunner.class, args);
}
}
There are more than one ways to solve this problem:
Create multiple profiles and assign them to the job runners. Activate one from command line using spring.profiles.active=jobrunner1, or spring.profiles.active=jobrunner1,jobrunner2 if you want to run more than one job. This solution lets you keep multiple CommandLineRunner implementations.
Specify which class to run, which in turn depends on how you're executing the code. If running using an IDE or a build tool like Maven or Gradle, you'll have to specify the main class name since the default resolution won't work. See this thread for a Maven-specific solution. If you're running the jar, see this thread. CommandLineRunner has a main method, so you can keep them, or just convert to regular main classes.

Can I create multiple entry points to a Spring Boot app?

In Spring Boot, a main class needs to be specified, which is the entry point to the app. Typically this is a simple class with a standard main method, as follows;
#SpringBootApplication
public class MySpringApplication {
public static void main(String [] args) {
SpringApplication.run(MySpringApplication.class, args);
}
}
This class is then specified as the main entry point when the application runs.
However, I want to run my code using a different main class using config to define this, And without using a different jar!! (I know rebuilding the jar will enable me to specify an alternative main class, but this effectively gives me two apps, not one! So, how can I do this to utilise one jar with two main classes and select the one to use via the Spring application.yml file?
I found an answer - use the CommandLineRunner interface...
So now I have two classes;
public class ApplicationStartupRunner1 implements CommandLineRunner {
#Override
public void run(String... args) throws Exception {
//implement behaviour 1
}
and
public class ApplicationStartupRunner2 implements CommandLineRunner {
#Override
public void run(String... args) throws Exception {
//implement behaviour 2
}
and how to switch between them in config..
#Configuration
public class AppConfig {
#Value("${app.runner}")
private int runner;
#Bean
CommandLineRunner getCommandLineRunner() {
CommandLineRunner clRunner = null;
if (runner == 1) {
clRunner = new ApplicationStartupRunner1();
} (else if runner == 2) {
clRunner = new ApplicationStartupRunner2();
} else {
//handle this case..
}
return clRunner;
}
}
and finally in the application.properties file, use
app.runner=1
I would stick with the original pattern of having just one main class and main method, however within that method you could configure where you want to go. I.e. rather than having 2 main methods and configuring which gets called make these 2 methods just normal methods, and create one main method which uses the config to determine which of your two methods get run.
The answer of jonny.l is fine.
Another very similar, but more manual/DIY solution is to get the ApplicationContext, from which you can get all other things:
#SpringBootApplication
public class App {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(App.class);
ConfigurableEnvironment env = context.getBean(ConfigurableEnvironment.class);
String mainApp = env.getProperty("app.runner");
if (mainApp.equals("Main1")) {
Main1 main1 = context.getBean(Main1.class);
main1.run();
} else if (mainApp.equals("Main2")) {
Main2 main2 = context.getBean(Main2.class);
main2.run();
}
}
}
#Service #Lazy
public class Main1 {
public void run() {}
}
#Service #Lazy
public class Main2 {
public void run() {}
}
#Lazyis used to prevent those beans from loading unnecessarily automatically.

What can Spring Boot Application classes extend?

I notice that Spring Boot application classes can extend other classes, but that the main(String[] args) methods generally all use SpringApplication.run(Application.class, args). The examples often use different annotations above the Application class definition.
This OP asks for a simple summary of three closely related questions:
1.) What are the possible classes that a Spring Boot Application.java class can extend?
2.) What are the intended uses of each of the extension options?
3.) And does the choice of a given extension also dictate specific annotations that must be added to the class definition?
From my research, I have identified the following three extension options:
1.) Extend nothing at all, as per this example:
#Configuration
#EnableAutoConfiguration
#ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
2.) Extend WebMvcConfigurerAdapter, as per this example:
#SpringBootApplication
#Controller
public class UiApplication extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(UiApplication.class, args);
}
}
3.) Extend SpringBootServletInitializer, as per this example:
#Configuration
#EnableAutoConfiguration
#EnableScheduling
#ComponentScan
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String... args) {
System.setProperty("spring.profiles.default", System.getProperty("spring.profiles.default", "dev"));
final ApplicationContext applicationContext = SpringApplication.run(Application.class, args);
}
}
Notice that I kept the annotations and minimal other stuff from the examples. This OP asks simply if specific annotation choices or minimal other stuff are dictated by the choice of extension.
Another one, which is not inheritance but it's composition, is to implement the CommandLineRunner interface so that you can perform some operations when the Spring Boot application starts up, like so:
#SpringBootApplication
public class DevopsbuddyApplication implements CommandLineRunner {
/** The application logger */
private static final Logger LOG = LoggerFactory.getLogger(DevopsbuddyApplication.class);
#Autowired
private UserService userService;
#Value("${webmaster.username}")
private String webmasterUsername;
#Value("${webmaster.password}")
private String webmasterPassword;
#Value("${webmaster.email}")
private String webmasterEmail;
public static void main(String[] args) {
SpringApplication.run(DevopsbuddyApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
User user = UserUtils.createBasicUser(webmasterUsername, webmasterEmail);
user.setPassword(webmasterPassword);
Set<UserRole> userRoles = new HashSet<>();
userRoles.add(new UserRole(user, new Role(RolesEnum.ADMIN)));
LOG.debug("Creating user with username {}", user.getUsername());
userService.createUser(user, PlansEnum.PRO, userRoles);
LOG.info("User {} created", user.getUsername());
}
}
Not sure if this is what you're looking for though.

How to get a reference of a running JavaFX application for testings with JUnit

it isn't a new issue for sure, but I couldn't find a nice solution for my problem, so I will try to find one on my own.
I have given an Application class:
import javafx.application.Application;
import javafx.stage.Stage;
public class TestApplication extends Application {
#Override
public void init() throws Exception {
// ...
super.init();
}
#Override
public void start(Stage primaryStage) throws Exception {
// ...
}
#Override
public void stop() throws Exception {
// ...
super.stop();
}
}
Now, I want to test methods from its controller and so on.. Not the GUI, but other things.
So, for this, I thought, I create an instance of this Application, start it and then I make something like instance.getXY(...). Is it the right purpose?
A little example for a JUnit class:
import org.junit.Test;
public class JUnitTests {
#Test
public void testFoo() {
// this starts the application, but I don't get a reference from it
javafx.application.Application.launch(TestApplication.class);
}
}
I've found this Launch JavaFX application from another class to get an refrence of the Application class. But it don't seems to be a nice solution for me.
How would you fix my testing problem?
Thanks for your help!

Categories

Resources