Since I haven't received an answer to my question. I've decided to try and find a different solution.
So, I've got a Java EE application that is deployed on a JBoss server and I'm asking if there's a way to initialize a database with some data, before the user starts interacting with the application. Apparently, a singleton bean that is executed at start-up is a problem (see my other question)
I don't know why the code from your other question fails, but you could try a couple of things:
Assuming you use maven, you could create a unit test to populate your database using JPA. The downside is that when you build with maven the test will always be executed (unless you specify -DskipTests)
Another thing you could try is using the ServletContextListener interface.
#WebListener
public class MyAppServletContextListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
// Initialize database here or create your
// own event for application startup and fire it
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
// Do nothing here
}
}
Edit:
3rd approach: you could use liquibase (http://www.liquibase.org/). Then have something like this: http://www.liquibase.org/documentation/changes/insert.html
Related
I have a service which handles CRUD operations for entities using H2 database. Previously during testing phase I used to have a csv file which "acted" as a database and upon application shutdown I saved all in-memory changes to entities to this csv file. Now I want to do the same, but for some reason I am not hitting any breakpoints in my onExit() method and therefore not saving data on application shutdown. I am still working out proper logic for selecting which entities to save, but for now I just want to be able to automatically save when I press Stop 'Application' button in Intellij.
#Component
public class MangaDataProvider {
private static MangaService mangaService;
#Autowired
public MangaDataProvider(MangaService mangaService) {
MangaDataProvider.mangaService = mangaService;
}
#PreDestroy
public static void onExit() {
mangaService.saveAll();
}
}
And then I have a onExit() method in Application:
#SpringBootApplication
public class Application extends SpringBootServletInitializer implements AppShellConfigurator {
public static void main(String[] args) {
LaunchUtil.launchBrowserInDevelopmentMode(SpringApplication.run(Application.class, args));
}
#PreDestroy
public void onExit() {
MangaDataProvider.onExit();
}
}
There is no guarantee that the shutdown hooks will be executed. They have a very limited time to execute. That means you code may be partially executed. You can try to add a Print statement, or a debug breakpoint. You will observe that the first statement is executed because it's super fast, but there is no time left to execute the rest of the method.
I good practice would be to call a service or an endpoint which "prepares" (in your case, it will persist your data) your application for shutdown. You call this service/endpoint then, when execution completed, you can safely terminate the application.
Many server application have a "prepare for shutdown" endpoint. Per example Jenkins ;)
I need to run some methods only once, when application starts for the first time. Is there any basic way to do this in Spring java/kotlin?
UPD:
For the first time means that i have new app that should run some methods on startup, but when i restart this app, i don't want it to run this method again
I would suggest that you use the ApplicationReadyEvent. According to the documentation, the ApplicationReadyEvent is an:
Event published as late as conceivably possible to indicate that the application is ready to service requests.
So, you could implement your own ApplicationListener listening for the ApplicationReadyEvent and run your code only when the application is ready, for example:
#Component
#Order(0)
class CustomApplicationListener implements ApplicationListener<ApplicationReadyEvent> {
#Override
public void onApplicationEvent(ApplicationReadyEvent event) {
// run your code
}
}
You can annotate your method with #PostConstruct (make sure you've made spring bean).
At the beginning of that method you can check if file "dummy.txt" exists in project directory if not proceed with method. At the end create file "dummy.txt".
You can also add property while starting java process first time like this:
java -DfirstTime=true -jar myjar.jar
Make firstTime false by default
I'm writing a #Repository/#Service integration test that leverages an embedded database. In my test class, I would like to preload my database with some data.
I'm currently using #BeforeEach to load in my sample data, however, this code is run upon each test in my class.
Is there any way that I can load in my test data after Spring application context has loaded, but before any test has been run?
My current approach:
#BeforeEach
public void before() {
repository.save(...); // -> prepopulates repository with sample data
}
#Test
public void testService() {
service.get(...); // -> gathers existing record
}
#Test
public void deleteById() {
service.delete(...); // -> deletes existing record
}
However... with this, I am required to flush out the records after every test. Otherwise any unique constraints can easily be violated.
Rather than using #BeforeEach which is required to run before every test... is it possible to load this in in a #BeforeAll kind of fashion that happens after the spring application context has been loaded?
Is there any way that I can load in my test data after Spring application context has loaded
Basically yes, I think you can do that:
The idea is to load the SQL data when the application context is started or in the process of being started.
For example, spring boot integration with Flyway works this way (the bean of Flyway is created and loaded). So, in theory, you could merely use Flyway with test migrations that will contain all the relevant SQL scripts of test data generation.
How can you do this technically?
Here is one way:
Create a special bean (just like the way it works with Flyway) that would depend on your repository and in post construct save the data:
#Component
public class SqlGenerationBean {
#Autowired
private MyRepository repo;
#PostConstruct
public void init() {
repo.save();
}
}
Another way of doing is to create a listener that will be called upon the application context started and again will call the same repo.save().
In both cases the bean/listener code should not be accessible from production (it's only for tests): so put it somewhere under src/test/java for example
Now once the application context is started you can use a neat trick:
Mark your tests with #Transactional annotation. Spring will wrap the code in an artificial transaction that will be rolled back automatically (even if the test succeeds) so that all the data that you'll modify during the test will be rolled back and basically before each test, you'll have the same state (that is identical to the state of the database when/after the application context starts). Of course, if you use DDL in the test, some databases can't make it a part of transaction but it depends on the database really.
Another interesting point here is that the application context can be cached even between the test cases (created only once), so keep this in mind.
In this case I would just create a constructor for the test class. It will be triggered before everything.
#BeforeEach runs before each tests but after all initialisations .
you can also just use Mockito and mock the result without need to clean and overcomplicate
Just add following snippet to your code. This is just like you can do to detect that Spring application is really started.
#Configuration
public class AppConfig implements ApplicationListener<ApplicationReadyEvent> {
/**
* This is to indicate in the logs when the application has actually started and everything is loaded.
*/
#Override
public void onApplicationEvent(ApplicationReadyEvent event) {
ApplicationContext context = event.getApplicationContext();
Environment env = context.getEnvironment();
// do what you want on application start
}
}
P.S. For database manipulation in test #Sql is the best candidate as was mentioned in comment.
I need to perform some work when the spring application is ready, something similar to #Scheduled but I want it to perform only once.
I found some ways to do it, such as using #PostConstruct on a bean, using #EventListener or InitializingBean, however, all of these ways does not match my need. If during the execution of this logic something goes wrong, I want to ignore it so the application starts anyway. But using these methods the application crashes.
Of course, I can surround the logic with try-catch and it will work. But, is there any more elegant way?
We faced a similar issue with our microservices , in order to run code just after startup we added a Component.
ApplicationStartup implements ApplicationListener<ApplicationReadyEvent>
Within the application to make a call to the services just after application startup, this worked for us.
#Component
public class ApplicationStartup implements ApplicationListener<ApplicationReadyEvent> {
#Autowired
YourService yourService;
#Override
public void onApplicationEvent(final ApplicationReadyEvent event) {
System.out.println("ApplicationReadyEvent: application is up");
try {
// some code to call yourservice with property driven or constant inputs
} catch (Exception e) {
e.printStackTrace();
}
}
}
When you use #PostConstruct for implementing a logic, the application is not ready yet, so it kind of contradicts your requirement. spring initializes the beans one by one (with respect to the dependencies between them.
After all it builds up the application context.
When the application context is fully initialized, spring indeed allows listeners to be run. So The listeners is a way to go - when the listener is invoked the application is ready.
In both cases (PostConstruct, EventListener) as long as you're not using try/catch block the application context will fail, because it waits till all the listeners will be done.
You can use #Async if you don't want the application context to wait for listeners execution. In this case the exception handling will be done by the task executor. See here
Personally I don't see any issue with try/catch approach
You can use #PostConstruct (as you said) but you must wrap your business in try catch and ignore it when it throws an exception.
Sample Code
#PostConstruct
void init() {
try {
//Your business
}
catch (Exception e) {
//Do nothing Or you can just log
}
I'm trying to wrap my head around Arquillian and perhaps even start using it in my project. I have a simple Java web app that deploys as a WAR to Tomcat.
In my project, I define a ServletContextListener impl so that I can execute code when Tomcat starts and stops the application.
I'm trying to write a super-simple Arquillian test class that uses ShrinkWrap and:
Confirms that my bundled WAR can be deployed to Tomcat and started without throwing exceptions; and
Can access a simple system property once the app is running (that the ServletContextListener checks for); and
Confirms that when Tomcat shuts down, no exceptions are thrown (clean shutdown)
Also, my class that implements ServletContextListener is called AppLifecycleManager:
public class AppLifeCycleManager implements ServletContextListener {
private String logLevel;
// Injected by Guice, but that's not really relevant for this question.
#Inject
private Logger logger;
// Getter and setter for logLevel and logger
#Override
public void contextInitialized(ServletContextEvent event) {
logLevel = System.getProperty("log.level");
}
#Override
public void contextDestroyed(ServletContextEvent event) {
logger.info("Peacefully shutting down the application.");
}
}
So far, here's my best attempt:
#RunWith(Arquillian.class)
public class MyFirstRealIntegrationTest {
#Deployment
public static Archive<?> createDeployment() {
// Haven't figured this part out yet, but for the sake of
// this question lets pretend this returns a properly-packaged
// WAR of my web app, the same that my Ant build currently produces.
}
#Test
public void shouldBeAbleToStartTomcatWithoutExceptions() {
// Given
Archive war = createDeployment();
// When - deploy war to Tomcat container
try {
// ??? how to access/init a Tomcat container?
TomcatContainer tomcat = new TomcatContainer(); // this is wrong
tomcat.start();
} catch(Throwable throwable) {
// Starting the container should not throw exceptions
Assert.fail();
}
}
#Test
public void shouldBeAbleToStopTomcatWithoutExceptions {
// Same setup as above test but stops tomcat and checks for
// thrown exceptions. Omitted for brevity.
}
#Test
public void shouldHaveAccessToSysPropsOnceRunning() {
// Here, deploy to the container and start it.
// Then, confirm that AppLifecycleManager correctly read
// the log.level system property.
// Given
Archive war = createDeployment();
TomcatContainer tomcat = new TomcatContainer();
// When - AppLifeycleManager should now read the system property
tomcat.start();
// Then - make sure log.level was set to "DEBUG" and that it was
// correctly read by AppLifeCycleManager.
Assert.assertTrue(war.getClass(AppLifeCycleManager.class)
.getLogLevel().equals("DEBUG"));
}
}
So, given my approach here, I immediately have several problems:
I'm not sure how to access/instantiate my Tomcat container so that it can even be started/stopped
I'm not sure how to actually execute tests from inside my running/deployed web app. In the 3rd test above I used war.getClass(AppLifeCycleManager.class).getLogLevel() to try and get access to a "live" class instance and check its logLevel property's runtime value, but I know this is wrong.
So I ask: how would a battle-worn Arquillian veteran write these 3 simple tests, and how do I actually go about performing tests on my "running" web app from inside the JUnit test? Thanks in advance.
I dont't think you should handle the startup/shutdown of tomcat in your test. I would by much easier if you used the embedded tomcat container: https://docs.jboss.org/author/display/ARQ/Tomcat+7.0+-+Embedded. In this case, arquillian will handle the startup and shutdown of tomcat.
You should create the deployment in the method annotated with #Deployment. Just read the following guide: http://arquillian.org/guides/getting_started/
You're almost there. createDeployment manages the lifecycle of your embedded container for you (starts and stops the virtual container automatically). That way, you're just focussing on the tests themselves. To write your integration tests, there's no "framework" or "Arquillian API" to code against. You just call classes and methods the way your main code does.
The key thing here is: your tests are actually running inside the container. If an exception occurs, or if your assert fails, the Arquillian runner throws an exception and stops the container. For your code example, where you're testing to see if you can read a system property:
#RunsWith(Arquillian.class)
public class MyArquillianTest {
#Deployment
public Archive<?> createDeployment() { ... }
#Test
public void shouldBeAbleToReadSysPropAtStartup() {
Assert.assertTrue(System.getProperty("log.level") != null);
}
}
Remember, Assert.assertTrue(System.getProperty("log.level") != null) Arquillian is "transporting" your code inside the container you configure it for. So that assert is actually running inside your deployed container.