Spring Boot - the best way to read data from database on startup - spring-boot

I would like to read data to List or Map from database on startup.
Which is the best way to do it? The Spring Boot version is 5.
Is the below solution is good?
#Component
public class ApplicationStartup
implements ApplicationListener<ApplicationReadyEvent> {
/**
* This event is executed as late as conceivably possible to indicate that
* the application is ready to service requests.
*/
#Override
public void onApplicationEvent(final ApplicationReadyEvent event) {
// here your code ...
return;
}
}
I'd like to storage data on static class, but I have doubt that is the best solution.

I don't quite understand what is your motive for doing so but for doing so you can create a bean using #Component and in that bean create a method with annotation #PostConstruct. you can do whatever you want in this method.

Using the ApplicationRunner interface is the best way to run code once the Spring boot context has loaded.
#Component
public class ApplicationStartup implements ApplicationRunner {
#Override
public void run(ApplicationArguments args) throws Exception {
}
}
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-spring-application.html#boot-features-command-line-runner

Related

Grpc Spring Boot Starter

I am trying to integrate a grpcService to my spring boot application. In this service class i have a jpaRepository which is #Autowired. When i run the server this repository is not injected( is null when i'm trying to use it).
#Service
public class MedicationPlanService extends medicationPlanGrpc.medicationPlanImplBase {
#Autowired
private MedicationPlanRepository medicationPlanRepository;
#Override
public void hello(MedicationPlan.HelloRequest request, StreamObserver<MedicationPlan.HelloResponse> responseObserver) {
List<MedicationPlan> medicationPlans = medicationPlanRepository.findAll();
MedicationPlan.HelloResponse.Builder response = MedicationPlan.HelloResponse.newBuilder();
response.setResponseMessage("hello");
responseObserver.onNext(response.build());
responseObserver.onCompleted();
}
}
#Component
public class GrpcServerStartConfiguration {
#PostConstruct
public void startGrpcServer() throws IOException, InterruptedException {
Server server = ServerBuilder.forPort(9091).addService(new MedicationPlanService()).build();
server.start();
System.out.println("gRPC server started");
server.awaitTermination();
}
}
When i try to use the medicationPlanRepository i realized that it is null.
Thanks in advance :).
Because you're creating MedicationPlanService with "new", it becomes a simple object, not a bean. And things such as DI don't work in this way.
Initialize these 2 classes correctly (via #ComponentScan or #Bean in #Configuration class). Then inject MedicationPlanService into GrpcServerStartConfiguration. The latter you can mark as #Configuration for better understaning btw.

Should I use #Transactional using #EnableTransactionManagement?

I've got a Spring Boot application. Everything works fine. I'm just trying to understand how does transaction manager work, because I have suspicion about my application. In particular, I'm a little confused about annotations.
Here is Application.java (main class):
#SpringBootApplication(exclude = ActiveMQAutoConfiguration.class)
#EnableScheduling
public class Application extends SpringBootServletInitializer
{
#Override
protected SpringApplicationBuilder configure (SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
public static void main(String[] args)
{
SpringApplication.run(Application.class, args);
}
}
config class DataConfig.java looks like:
#Configuration
#EnableTransactionManagement
#ComponentScan("com.pr.hotel")
#EnableJpaRepositories("com.pr.hotel")
#PropertySource("classpath:application.properties")
public class DataConfig
{
// code
}
I'm worry about #EnableTransactionManagement. What exactly does this annotation mean? Should I use #Transactional in this case (I don't)?
#EnableTransactionManagement does exactly what it says:
Enables Spring's annotation-driven transaction management capability,
similar to the support found in Spring's XML namespace.
Yes, you should still use #Transactional annotation on methods that you want to wrap in a transaction. In the following example the result of saveSomething() wouldn't be applied if maybethrowaneException() threw an exception. Be careful to use org.springframework.transaction.annotation.Transactional and not javax.transaction.Transactional.
The #Transactional annotation tells Spring to control when the data are flushed to the database (typically once the method successfully completes). Without the annotation the data would be flushed immediately.
It's a mechanism to prevent incomplete changes being written to the database when something goes wrong. Further reading: https://dzone.com/articles/how-does-spring-transactional
#Service
public class DataTransformer() {
#Transactional
public void doETL() throws Exception {
loadSomeEntities();
saveSomething();
maybethrowanException();
saveSomethingElse();
}
}

init method in jersey jax-rs web service

I'm new with jax-rs and have build a web service with jersey and glassfish.
What I need is a method, which is called once the service is started. In this method I want to load a custom config file, set some properties, write a log, and so on ...
I tried to use the constructor of the servlet but the constructor is called every time a GET or POST method is called.
what options I have to realize that?
Please tell, if some dependencies are needed, give me an idea how to add it to the pom.xml (or else)
There are multiple ways to achieve it, depending on what you have available in your application:
Using ServletContextListener from the Servlet API
Once JAX-RS is built on the top of the Servlet API, the following piece of code will do the trick:
#WebListener
public class StartupListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent event) {
// Perform action during application's startup
}
#Override
public void contextDestroyed(ServletContextEvent event) {
// Perform action during application's shutdown
}
}
Using #ApplicationScoped and #Observes from CDI
When using JAX-RS with CDI, you can have the following:
#ApplicationScoped
public class StartupListener {
public void init(#Observes
#Initialized(ApplicationScoped.class) ServletContext context) {
// Perform action during application's startup
}
public void destroy(#Observes
#Destroyed(ApplicationScoped.class) ServletContext context) {
// Perform action during application's shutdown
}
}
In this approach, you must use #ApplicationScoped from the javax.enterprise.context package and not #ApplicationScoped from the javax.faces.bean package.
Using #Startup and #Singleton from EJB
When using JAX-RS with EJB, you can try:
#Startup
#Singleton
public class StartupListener {
#PostConstruct
public void init() {
// Perform action during application's startup
}
#PreDestroy
public void destroy() {
// Perform action during application's shutdown
}
}
If you are interested in reading a properties file, check this question. If you are using CDI and you are open to add Apache DeltaSpike dependencies to your project, considering having a look at this answer.

Catch application stop event for Spring-boot application

Is there a clean way to detect when a spring-boot application is stopped and perform some action before? Kind of CommandLineRunner for stopping a service
Thanks in advance
Similar to ApplicationReadyEvent you can use ContextClosedEvent:
#Component
public class ContextClosedEventListener {
#EventListener(ContextClosedEvent.class)
public void onContextClosedEvent(ContextClosedEvent contextClosedEvent) {
System.out.println("ContextClosedEvent occurred at millis: " + contextClosedEvent.getTimestamp());
}
}
I've come up with this solution. If you have better one, feel free to share
#Component
public class PortalServiceLifeCycle implements CommandLineRunner {
static final Logger LOGGER = LoggerFactory.getLogger(PortalServiceLifeCycle.class);
#Override
public void run(String... arg0) throws Exception {
LOGGER.info("###START FROM THE LIFECYCLE###");
}
#PreDestroy
public void onExit() {
LOGGER.info("###STOP FROM THE LIFECYCLE###");
}
}
Don't know if you have resolve this problem perfectly. I meet this issue recently, and have got a solution that a little different.
Firstly, my Spring boot Application is a Tomcat embedded one. (The second method of this issue doesn't depends on the web structure. don't mad, my friend.) In this case, it's naturally to get the idea of catch the stop event by register a listener. I do it like this,
#WebListener
public class HelloListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("HelloListener contextInitialized");
}
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("HelloListener contextDestroyed");
}
}
and, at the same time, add the annotation #ServletComponentScan on your Application class.
Surely, there are some other ways to register a ServletContextListener, and once you registered it, you can get the stop event in the contextDestroyed function.
BUT, that don't match my issue very much. I must catch the stop event BEFORE the Spring Beans being destroyed. And here comes the second solution.
modify your application main method like the follow:
SpringApplication application = new SpringApplication(DemoApplication.class);
application.addListeners(new MyListener());
application.run(args);
and provide the defination of class MyListener:
class MyListener implements ApplicationListener<ContextClosedEvent>{
#Override
public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {
// your code here
}
}
NOTE: the second solution has nothing to do with Tomcat or other web container. The ContextClosedEvent isn't introduced in the Spring document, but I found it in the source, it's very useful i think.
I will be very glad if this can help some one.
It depends what you want to do but one thing you could do is have a bean that implements SmartLifecycle and implement the stop method. Whenever the context is being stopped, you'd get a callback. Note that it does not necessarily means that the process is shutting down. If you want to invoke some code when that happens, I'd register a shutdown hook as Sven wrote in a comment.

How to implement ServletContextListener in struts2, spring, hibernate application?

In my application I want to store some of my data in ServletContext as its going to be used through out the application. Data are saved in a database. All the configurations are made through integrating struts2, spring, hibernate. Problem is that, I am finding difficulties to fetch the data from the database. Spring is unable to inject the dao impl class to the class that is implementing the ServleltContextListener. Can anyone please tell me how to do this? Or is there any alternative?
Try this
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
public class MyListener implements ServletContextListener
{
/**
* #see javax.servlet.ServletContextListener#contextInitialized
* (javax.servlet.ServletContextEvent)
*/
#Override
public void contextInitialized(ServletContextEvent sce)
{
WebApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
Object yourDaoImplClass = applicationContext.getBean("your_bean_name_or_bean_id");
//You can type cast yourDaoImplClass to your object
}
/**
* #see javax.servlet.ServletContextListener#contextDestroyed
* (javax.servlet.ServletContextEvent)
*/
#Override
public void contextDestroyed(ServletContextEvent sce)
{
}
}
Hope this works. Let me know how it goes.
The best approach would be to implement Spring's ServletContextAware interface and then use an #PostConstruct or afterPropertiesSet method to add items to the servlet context.

Resources