Java Running Thread after First Thread finish processing - java

I am trying run a thread after the first one finish.
Let me explain more, I have an automation test code that preform some tests using selenium and Appium.
A report is generated with a test result after the process is completed.
I also have a send mail service that will send this report after they are generated
The reports is only generated one process finish execution
What I am trying to do.
Lets say I have two main methods in different classes the first one is the one that execute tests and generate report the second one hold the mail services
I want the mail services to execute after the report is generated from the first method.
This Demo Class is the first one to execute as it hold all test process and the report is only generated when the process is finished.
package runners.Demo;
import io.cucumber.core.cli.Main;
public class Demo{
public static void main(String[] args) throws InterruptedException {
final String[] arguments = new String[]{
"classpath:","src/main/java",
"--glue", "stepDefinition",
"--tags", "#sdkG",
"-p","pretty",
"-p", "html:src/test/java/reports/sanity-report.html",
"-p","pretty",
"-p","com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter:",
};
Main.main(arguments);
}}
MailHandler class hold code for mail I want to make this class to run after the first (Demo.class)(Process finished with exit code 0) is finished so the mail can send the generated report after it being created.
package runners;
public class MailHandler extends Thread implements Runnable{
public static void main(String[] args){
HOLD Mailing Code.......
}}

Related

Appropriate way to implement a cli Application which also uses the service profile with Micronaut

I've no problem in creating a REST Server or a Picocli CLI Application.
But what if I want to have both in one Application?
The thing is, I want to have an Application which provides some business logic via REST Server (no problem there), but in some other cases I want to trigger the business logic via CLI without starting the HTTP Server (eg. for CI/CD).
I'm not sure if I run into problems if I start the app via
PicocliRunner.run(Application.class, args) and if a specific argument is given run the Server with Micronaut.run(Application.class);, since they create a different context.
Does anyone know a proper way to achieve this?
This is how I solved it:
import io.micronaut.configuration.picocli.PicocliRunner;
import io.micronaut.runtime.Micronaut;
import picocli.CommandLine.Command;
import picocli.CommandLine.Parameters;
#Command(
name = "RestAndCliExample",
description = "...",
mixinStandardHelpOptions = true
)
public class Application implements Runnable {
private enum Mode {serve, run}
#Parameters(index = "0", description = "Execution mode: ${COMPLETION-CANDIDATES}")
private Mode mode;
public static void main(String[] args) throws Exception {
args = new String[]{"run"};
PicocliRunner.run(Application.class, args);
}
public void run() {
if (Mode.serve.equals(mode)) {
// Start REST API
Micronaut.run(Application.class);
} else {
// TODO run code directly
}
}
}
One way to accomplish this is to #Inject the ApplicationContext into your #Command-annotated class. This allows your command to use the same application context instead of needing to start a separate one.
Then, in your run method, you can start the REST server by obtaining the EmbeddedServer from the application context and calling start on it, or you can execute the functionality directly without the REST server.
See also this answer for more detail: https://stackoverflow.com/a/56751733/1446916

How to run a method after passing through a tag in the feature file?

I have a scenario in my feature file that contains two tags
#tag1, #tag2
Scenario: This is a test
Given I open the website
When I log in
Then the account page is open
Now #tag is part of a cucumber serenity runner and this works in isolation (before the implementation of #tag2):
#RunWith(CucumberWithSerenity.class)
#CucumberOptions(features="...features/", glue = {".../steps"}, tags = {"#tag1"} )
public class Tag1Runner extends Hooks {
#BeforeClass
public static void startAppium() {
AppiumServerController.startAppiumServer();
}
#AfterClass
public static void stopAppium() {
AppiumServerController.stopAppiumServer();
}
Now what I also want to do is run #tag2, but this only runs after the test has been completed. This is because the method that occurs in #tag2 should not be part of the scenario to test, but should complete a clean up after the test has ran.
Now if I include the following method below, when I run the feature file as it is displayed above, nothing happens.
How can I implement #tag2 to work as mentioned?
public class Hooks{
#After("#tag2")
public void completeCleanUp() {
//code to perform clean up...
}
}
If you are trying to run an After hook after each scenario tagged with "#tag1" in your example, you should mark the After hook with "#tag1". For more information on tagged hooks, please refer to the Cucumber documentation.

Unit Testing a Client-Server Application in Java

I'm working on a simple client-server application, and I'm supposed to initialize my client and server objects in separate threads. The server contains a database of all of the courses in some specific departments at my university, and the GET request gets all of the classes in the requested department and sends it back to the client. While I was able to test everything perfectly fine in a main method, unit testing was just not working. Below is my code for the unit test:
import client.Client;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import server.Server;
public class ClientServerTest {
private static String file = "";
#BeforeClass
public static void setFile(){
file = System.getProperty("file");
}
#Before
public void startServerTest(){
Thread serverThread = new Thread(() -> {
new Server(file);
});
serverThread.start();
}
#Test
public void getTest(){
Client client = new Client();
Assert.assertTrue(client.submitRequest("GET COM"));
Assert.assertTrue(client.submitRequest("GET MAT"));
Assert.assertTrue(client.submitRequest("GET BIO"))
}
}
When I run the test, the server test passes, I get the following output for the getTest() test:
java.net.ConnectException: Connection refused: connect
I've been looking around trying to find the best way to get unit tests to work with threads, but I can't seem to figure it out. Any help would be most appreciated.
First, as my fellows stated, that's far away from a unit test but an integration or end-to-end test.
The problem with your test might be that some threads outperforms other threads creating randomly failing tests so you need some option to synchronize them.
I can say that it's absolutely possible to do this kind of testing with JUnit but there are some key concepts to put into practice to make such tests, involving multiple threads, reproducible (not flaky) and any useful.
Without seeing the implementation of Server class it's pretty difficult but I try to sum up the hints that hopefully put you on the right track.
First:
Create your Server class and all other dependencies inside the same thread (preferably in the main thread).
public static void main(String[] args) {
Foo otherInstance = new Foo(...);
Bar anotherInstance = new BarImpl(otherInstance,...);
Server server = new Server(otherInstance, anotherInstance);
server.start(); // blocking until app is stopped in a graceful way and where real application logic starts
// not more to do here
}
Important is that constructors must not do any "work" apart from assigning instance variables like this.someVar = someVar. The concept behind that is called dependency injection and makes your life a lot easier especially if you use a library.
Second:
Your app needs hooks, that tests can plug into to intercept your logic, where you can make threads halt and wait for other events happen that are necessary to make your tests work. Where to plug into depends highly on your application. It's most likely necessary to specify different implementations for some classes inside your tests thus differently wiring the app's dependency graph.
To accomplish that synchronizations aids like CountDownLatch are your best friends inside the test class.
#Test
public void someTest() {
// or move the instantiation logic to the #Before setup method
final CountDownLatch isConnected = new CountDownLatch(1);
Foo otherInstance = new Foo(...);
Bar anotherInstance = new BarTestImpl(otherInstance,...);
// here we plug into the connected event
anotherInstance.setConnectionListener(() -> { isConnected.countDown(); }
Server server = new Server(otherInstance, anotherInstance);
server.startAsync(); // not blocking
...
// test logic starting, do some assertions or other stuff
...
// block until connected event is received
isConnected.await(1, TimeUnit.SECONDS);
// do some assertions
assertTrue(server.isConnected());
...
}
This example is scratching on the surface of what is possible and how to leverage this concept for maintaining a high level of automated testing but it should show the idea behind.
Normally a UnitTest should only test a single component. The "Unit".
You whant to do some kind of integration testing. So you have to ensure that every component that you need for your #Test is up an running before #Test is called.
I'm not sure if JUnit is the best framework for this. But you can add a check in the #Before method that will sleep the main thread until the server is running.
For example:
#Before
public void startServerTest(){
Server = new Server();
Thread serverThread = new Thread(() -> {
server.init(file);
});
serverThread.start();
while (!server.isRunning() {
Thread.sleep(1000);
}
}

Java Command Line when daemon is running

We all know what the code below does
class Demo{
public static void main(String b[]){
System.out.println("Argument one = "+b[0]);
System.out.println("Argument two = "+b[1]);
}
}
My question (infact curiosity) is, if this application is a daemon that is running and java based server waiting for clients to do socket stuff with it, can I run the application again, and pass new parameters to it ? Basically I am looking at not implementing a cli kinda thing. I need it simple.
Edit : I want to change / add more parameters at runtime. But if I run the app with new parameters, wont it start another instance ?
No, you can't modify the arguments passed after the application started.
The array used to retreive the parameters is populated when it starts and cannot be altered.
If the application is a server, you should be able to implement a CLI rather easily with a simple thread waiting for input.
Seems like you have an existing application that is being run as a command line application right now. It is being invoked as and when required from command line passing the appropriate command line parameters. And now what you would like to do is host this same application as a daemon service which gets invoked as and when the parameters come over a port it is listening to.
Assuming your goal is the above and for whatever reason you want to retain the above main() signature, the key is to realize that the main() method is also like any other static method which can be invoked by a class reference. So the following is possible:
class SocketListener extends Thread {
public void run() {
// Code for listening to socket that calls invokeDemo()
// method below once it detects the appropriate args.
}
private void invokeDemo(String[] args) {
// You can invoke the main method as any other static method.
Demo.main(args);
}
}
This would just treat Demo class as part of a library it is using and not launch any other application. If you do want to launch it as an application (because of some special reason), you would need to use the Process and Runtime classes of java.

Using monit with java

I am using the tool monit to start/stop a process. I have a java file as follows:
class test {
public void start()
{
//do something
}
public void stop()
{
//do something
}
}
I want to call the start func when a start command is issued from monit and vice versa. I cannot seem to find a good tutorial explaining what steps I need to take for executing the start and stop method. do I need to write a bash script? and monit will call the bash script which in turn calls the java method?
The entry point into a java program is the main method.
public static void main(String [] args)
{
// args carry the command line arguments.
}
In your case, you should create an instance of test and call start() method on that instance.
public static void main(String [] args)
{
test obj = new test();
obj.start();
}
Java's Runtime class provides an option to add a shutdown hook that gets called when the java program is being terminated. You write a simple thread class that has access to the test instance created in the main method above so that when the shutdown hook thread's run method is called, you delegate it to test instance's stop method.
Hope this helps.

Categories