2

Very new to WebSphere as well as packaging Java.

I need to take a Java project that we've been running from the command line as an executable Jar and make it run from WebSphere (since the admin user has been getting auto-logged out at midnight).

I've looked at creating a WAR file, but the ant examples I've looked at invoked a lot of WEB-INF dependencies ... but this project doesn't have that. It has a main entry point in the code.

EARs seem to require EJBs, which I don't think this project uses. Seeing as EJBs have been on their way out for a while I'm not as up to speed on them.

My questions are: What is the simplest way to put my executable JAR into WebSphere?

Bonus points: Do EAR files require EJBs in the project? If so, how do I know if this project invokes them?

micahhoover
  • 2,101
  • 8
  • 33
  • 53
  • Do you want to run the main method when WebSphere is started, or on some interval, or when someone hits some website? – kgibm Nov 02 '18 at 01:32
  • 1
    EAR doesnt require EJBs, but require either WAR module or EJB module. You can also deploy plain WAR. Is your application a Spring Boot? What your application does? – Gas Nov 02 '18 at 02:36
  • @kgibm: when WebSphere is started – micahhoover Nov 02 '18 at 13:19
  • @Gas: I can see why you would guess Spring Boot, but there's nothing that modern in our stack here. Basically it monitors a directory that gets files plopped into it from an sftp source. I want it to start watching that directory as soon as it comes up. – micahhoover Nov 02 '18 at 13:21
  • So whats the point of having that in WebSphere if it doesnt have UI nor is accessible remotely? Just add that to corn and it will be automatically started when the system boots up. – Gas Nov 02 '18 at 15:09
  • What version of WebSphere are you running? – kgibm Nov 03 '18 at 16:52
  • @kgibm: WebSphere v 8.5.5.13 – micahhoover Nov 19 '18 at 21:17
  • @Gas: I looked at a couple places on the interwebs explaining how to couple a class to run on startup, but I didn't see enough details about how WebSphere knows to start it. Perhaps you have a URL or example? – micahhoover Nov 19 '18 at 21:20
  • You can either create servlet or listener class that will run on startup - see https://stackoverflow.com/questions/18808853/load-on-start-up-using-annotation-in-java, or you can create startup bean - https://stackoverflow.com/questions/6820838/startup-bean-not-called depending on what actually you want to do. – Gas Nov 20 '18 at 17:21

1 Answers1

1

The simple answer is to create a war application with a @WebListener:

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class ServletInitializer implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println(toString() + " contextInitialized started");
        String[] args = new String[] {};
        MainClass.main(args);
        System.out.println(toString() + " contextInitialized finished");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }
}

Replace MainClass.main(args); with your application call (and add any JAR dependencies into WEB-INF/lib).

The thing I don't like about the above is that it's not great to perform intense work during startup. This may make problem determination harder and certain capabilities (e.g. runtime diagnostic trace modification) are unavailable during startup.

You could create a WAS-specific solution by using AdminClient to subscribe to the Server MBean's Stateful notifications.

Otherwise, a standardized way would be to have an EJB @Startup bean which uses the TimerService to start work after some delay which is empirically determined to be an average application server startup time. For example:

import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;

@Singleton
@Startup
public class DeferredInitializer {

    public static final int DELAY = Integer.getInteger("DeferredInitializer.DELAY", 60000);

    @Resource
    TimerService timerService;

    @PostConstruct
    private void init() throws Throwable {
        System.out.println(toString() + " init entry");
        TimerConfig timerConfig = new TimerConfig();
        timerConfig.setPersistent(false);
        timerService.createSingleActionTimer(DELAY, timerConfig);
        Calendar c = new GregorianCalendar();
        c.add(Calendar.MILLISECOND, DELAY);
        System.out.println(toString() + " timer estimated to pop in (" + DELAY + "ms) ~@ " + c.getTime());
        System.out.println(toString() + " init exit");
    }

    @Timeout
    public void timeout(Timer timer) {
        System.out.println(toString() + " timeout entry");
        String[] args = new String[] {};
        MainClass.main(args);
        System.out.println(toString() + " timeout exit");
    }
}

Specify the delay with the generic JVM argument -DDeferredInitializer.DELAY=X (X in milliseconds).

kgibm
  • 852
  • 10
  • 22