14

I am working on an application which is running on Glassfish. I am supposed to convert the servlets to proper restful stuff, by using jax-rs and jersey.

I have been trying to find a workaround for init() method, but till now i failed.

Here is the original part, using servlets:

import javax.servlet.*

public void init(ServletConfig config) throws ServletException {
super.init(config);
 if (!isRunning() == true)) {
     /* Do some stuff here*/
 }

 logger.info("Deamon has started");
}

and this one which i am trying to use jax-rs

import javax.ws.rs.*
import javax.servlet.*

public void init(@Context ServletConfig config) throws ServletException {
//uper.init(config);
if (!isRunning() == true)) {
  /* Do some stuff here*/
}

logger.info("Deamon has started");
}

I have checked mailing lists and googled around but couldnt find a way which could work for this case.

any ideas how to achieve the same behaviour with servlets for init method?

McDowell
  • 107,573
  • 31
  • 204
  • 267
denizdurmus
  • 1,289
  • 1
  • 13
  • 39
  • Daemon = background process doing useful work; demon = evil spirit, deamon doesn't exist. – foo Feb 21 '19 at 10:51

4 Answers4

11

finally, after googling a little bit more, i found a proper solution.

basically, i have extended public class ContextListener implements ServletContextListener class and implemented the abstract method public void contextInitialized(ServletContextEvent sce) which is called when the application is loaded. I have moved the logic from the servlet to here for doing the initialization and other config settings, then it was smooth.

denizdurmus
  • 1,289
  • 1
  • 13
  • 39
  • 1
    This is definitely the best solution, especially if You want to write to file on server shutdown. Main purpose of my comment is to thank You for this great answer, and to help future Googlers in finding this neat solution more easily. Here is a great [example-SSCCE](https://www.mkyong.com/servlet/what-is-listener-servletcontextlistener-example/). – Aleksandar Feb 11 '17 at 15:28
  • 4
    actually if you're on jersey you can use `ApplicationEventListener` instead – svarog Sep 07 '17 at 18:41
6

Use @PostConstruct; example from a web application:

@Context
private ServletContext context;

@PostConstruct
public void init() {
  // init instance
}
McDowell
  • 107,573
  • 31
  • 204
  • 267
  • didnt work... The method was not called while the application was initialized. could it be because of some internal stuff with glassfish? or am i missing some other configs? – denizdurmus May 30 '13 at 00:07
  • This works for me on Glassfish 3.1.1 using the provided Jersey implementation. If you're using NetBeans, create a new project using _Samples > Java Web Services > REST: Hello World (Java EE 6)_ and compare your descriptors (web.xml, etc.) to the ones used there. – McDowell May 30 '13 at 04:49
  • 1
    @PostConstruct methods can't throw checked exceptions, which is cumbersome. – Alkanshel Jun 04 '16 at 00:30
  • 2
    Didn't work for me in RESTEasy (deploying to JBoss EAP 6.2) – Marcus Junius Brutus Feb 02 '17 at 00:04
  • @PostConstruct not invoked in Wildfly10.1.0 – mirec Feb 26 '17 at 21:12
5

Here is how I implemented an init method in Jersey 2.6/JAX-RS in case it helps anyone. This is using the suggestion of @PostConstruct.

The code below starts the web app, scans for all resources in the package and initialises a static test counter with 3:

package com.myBiz.myWebApp;

import com.sun.net.httpserver.HttpServer;
import java.io.IOException;
import java.net.URI;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ws.rs.core.Application;

public class WebApplication extends Application {
    // Base URI the HTTP server will listen to
    public static final String BASE_URI = "http://localhost:8080/";
     public static int myCounter = 0;

    /**
     * Starts a server, initializes and keeps the server alive
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        final HttpServer server = startServer();
        initialize();
        System.out.println("Jersey app started\nHit enter to stop it...");
        System.in.read();
        server.stop(1);
        System.out.println("Server stopped successfully.");
    }

    /**
     * Default constructor
     */
    public WebApplication() {
        super();
    }

    /**
     * Initialize the web application
     */
    @PostConstruct
    public static void initialize() {
        myCounter = myCounter + 3;
    }

    /**
     * Define the set of "Resource" classes for the javax.ws.rs.core.Application
     */
    @Override
    public Set<Class<?>> getClasses() {
        return getResources().getClasses();
    }

    /**
     * Scans the project for REST resources using Jersey
     * @return the resource configuration information
     */
    public static ResourceConfig getResources() {
        // create a ResourceConfig that scans for all JAX-RS resources and providers in defined package
        final ResourceConfig config = new ResourceConfig().packages(com.myBiz.myWebApp);
        return config;
    }

    /**
     * Starts HTTP server exposing JAX-RS resources defined in this application.
     * @return HTTP server.
     */
    public static HttpServer startServer() {
        return JdkHttpServerFactory.createHttpServer(URI.create(BASE_URI), getResources());
    }
}

And here is the associated build.xml, which needs to refer to this class (WebApplication):

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <!-- The following instantiates the class WebApplication, resources are scanned on WebApplication object creation and init is done as well -->
    <servlet>
        <servlet-name>myWebApp</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.myBiz.myWebApp.WebApplication</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>myWebApp</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

From here, just create a "test" resource to check the counter:

package com.myBiz.myWebApp;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.myBiz.myWebApp.WebApplication;

@Path("/test")
public class ResourceTest {
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getResource() {
        WebApplication.myCounter++;
        return "Counter: " + WebApplication.myCounter;
    }
}

The counter should be initialized with value 3 + 1, and subsequently refreshing the resource will just increase it by 1.

Pelpotronic
  • 550
  • 6
  • 11
2

You can create a ServletContextClass and add the <listener> tag to the web.xml

The listener tag loads the ServerContextClass at start-up of your web application. Inside the contextInitialized method you can access the context as below:

public void contextInitialized(ServletContextEvent arg0){
    ServletContext context = arg0.getServletContext();
} 

Refer to similar example here

Kobby Kan
  • 81
  • 1
  • 3