ServletContextListener defers server start

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

ServletContextListener defers server start

Dirk Olmes
Hi,

I'm using an embedded Jetty to set up a servlet context. My code looks
quite similar to what's in the "Embedding ServletContexts" section of
the "Embedding Jetty" chapter of the Jetty docs.

I noticed that the server (more correctly the ServerConnector) won't be
ready to accept connections unless my servlets have started up. Now I
have a ServletContextListener that takes a long time to start up.

Would it be possible to configure Jetty in such a way that it already
accepts connections and answers e.g. with a 503 status until the servlet
context is finally up and running?

-dirk
_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users
Reply | Threaded
Open this post in threaded view
|

Re: ServletContextListener defers server start

Joakim Erdfelt-8
Sounds like the initial deployment on Server.start() is the reason you are experiencing this.

Your environment would need to delay deployment until after the server has started up.
That would be a new feature / configuration (and not that hard to implement either)
Can you file an issue for a new feature at https://github.com/eclipse/jetty.project/issues

And the extra requirement of a 503 before the webapp is available is a new feature that Jetty does not have.
That would likely need to be a custom Handler at the end of your Handler tree (but before the DefaultHandler) to
check the submitted context path and return 503 in those situations. 
(as if it reached that custom handler, that means the webapp isn't there yet)
That can also be a new feature, submit the idea at https://github.com/eclipse/jetty.project/issues

Joakim Erdfelt / [hidden email]


On Fri, Oct 4, 2019 at 9:02 AM Dirk Olmes <[hidden email]> wrote:
Hi,

I'm using an embedded Jetty to set up a servlet context. My code looks
quite similar to what's in the "Embedding ServletContexts" section of
the "Embedding Jetty" chapter of the Jetty docs.

I noticed that the server (more correctly the ServerConnector) won't be
ready to accept connections unless my servlets have started up. Now I
have a ServletContextListener that takes a long time to start up.

Would it be possible to configure Jetty in such a way that it already
accepts connections and answers e.g. with a 503 status until the servlet
context is finally up and running?

-dirk
_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users

_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users
Reply | Threaded
Open this post in threaded view
|

Re: ServletContextListener defers server start

Greg Wilkins


Dirk,

Note that you can actually achieve this with just a little bit of work:

Write a simple context (extend context handler) that all it does is send a 503 with whatever message you want.
Deploy both that context and your context at the same context path.  The 503 context will handle all the requests as it is first.
Once your context is started, stop and/or remove the 503 context.





On Sat, 5 Oct 2019 at 00:48, Joakim Erdfelt <[hidden email]> wrote:
Sounds like the initial deployment on Server.start() is the reason you are experiencing this.

Your environment would need to delay deployment until after the server has started up.
That would be a new feature / configuration (and not that hard to implement either)
Can you file an issue for a new feature at https://github.com/eclipse/jetty.project/issues

And the extra requirement of a 503 before the webapp is available is a new feature that Jetty does not have.
That would likely need to be a custom Handler at the end of your Handler tree (but before the DefaultHandler) to
check the submitted context path and return 503 in those situations. 
(as if it reached that custom handler, that means the webapp isn't there yet)
That can also be a new feature, submit the idea at https://github.com/eclipse/jetty.project/issues

Joakim Erdfelt / [hidden email]


On Fri, Oct 4, 2019 at 9:02 AM Dirk Olmes <[hidden email]> wrote:
Hi,

I'm using an embedded Jetty to set up a servlet context. My code looks
quite similar to what's in the "Embedding ServletContexts" section of
the "Embedding Jetty" chapter of the Jetty docs.

I noticed that the server (more correctly the ServerConnector) won't be
ready to accept connections unless my servlets have started up. Now I
have a ServletContextListener that takes a long time to start up.

Would it be possible to configure Jetty in such a way that it already
accepts connections and answers e.g. with a 503 status until the servlet
context is finally up and running?

-dirk
_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users
_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users


--

_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users
Reply | Threaded
Open this post in threaded view
|

Re: ServletContextListener defers server start

Dirk Olmes
On 10/5/19 2:07 AM, Greg Wilkins wrote:
> Dirk,

Hi Greg,

> Note that you can actually achieve this with just a little bit of work:
>
> Write a simple context (extend context handler) that all it does is send a
> 503 with whatever message you want.
> Deploy both that context and your context at the same context path.  The
> 503 context will handle all the requests as it is first.
> Once your context is started, stop and/or remove the 503 context.

Thanks for the hint but I'm afraid it is not as simple as you describe -
or I'm still missing bits.

This is what I do for testing:

// this is the handler that just answers 503
ContextHandler duringStartup = new DuringStartupHandler();
// my app
ServletContextHandler theRealContext = ....
HandlerList handlerList = new HandlerList(duringStartup, theRealContext);
server.setHandler(handlerList);

Both handlers participate in the normal server startup, though, which
means that the ServerConnector still does not listen before the real app
context is ready. I'd think that my application context should be
started in a separate thread? Is there anything already present in Jetty
to accomplish this?

The full source of my tests is available here:
https://github.com/dirk-olmes/jetty-delayed-context-startup

-dirk
_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users
Reply | Threaded
Open this post in threaded view
|

Re: ServletContextListener defers server start

Bill Ross-2
Why not have a ContextHandler that starts a setup thread on init, and
answers 503 until that thread is done?

Bill

On 10/7/19 2:10 AM, Dirk Olmes wrote:

> On 10/5/19 2:07 AM, Greg Wilkins wrote:
>> Dirk,
> Hi Greg,
>
>> Note that you can actually achieve this with just a little bit of work:
>>
>> Write a simple context (extend context handler) that all it does is send a
>> 503 with whatever message you want.
>> Deploy both that context and your context at the same context path.  The
>> 503 context will handle all the requests as it is first.
>> Once your context is started, stop and/or remove the 503 context.
> Thanks for the hint but I'm afraid it is not as simple as you describe -
> or I'm still missing bits.
>
> This is what I do for testing:
>
> // this is the handler that just answers 503
> ContextHandler duringStartup = new DuringStartupHandler();
> // my app
> ServletContextHandler theRealContext = ....
> HandlerList handlerList = new HandlerList(duringStartup, theRealContext);
> server.setHandler(handlerList);
>
> Both handlers participate in the normal server startup, though, which
> means that the ServerConnector still does not listen before the real app
> context is ready. I'd think that my application context should be
> started in a separate thread? Is there anything already present in Jetty
> to accomplish this?
>
> The full source of my tests is available here:
> https://github.com/dirk-olmes/jetty-delayed-context-startup
>
> -dirk
> _______________________________________________
> jetty-users mailing list
> [hidden email]
> To change your delivery options, retrieve your password, or unsubscribe from this list, visit
> https://www.eclipse.org/mailman/listinfo/jetty-users
_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users
Reply | Threaded
Open this post in threaded view
|

Re: ServletContextListener defers server start

Dirk Olmes
On 10/7/19 11:21 AM, Bill Ross wrote:
> Why not have a ContextHandler that starts a setup thread on init, and
> answers 503 until that thread is done?

That's sort of what I currently do (starting a setup thread from the
main servlet's init method) but that causes all kinds of trouble because
the servlet context accepts requests before all the app logic is ready.

Based on your suggestion combined with Greg's before I came up with this
approach: Register a ContextHandler that answers 503 and let the server
start normally. After the server is started I launch the setup thread
where I register the real app context with the server and manually send
it a start(). After the context is started I unregister the
ContextHandler that answers 503.

The code is here:
https://github.com/dirk-olmes/jetty-delayed-context-startup/tree/deferred_context_startup

Ok, this approach works. But I was hoping that Jetty supported something
like that out of the box.

-dirk
_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users
Reply | Threaded
Open this post in threaded view
|

Re: ServletContextListener defers server start

Bill Ross-2
Would anything like these chunks from my code work for you? The secret
is checking status in doGet().


public class GetMult extends HttpServlet {

     private ServletData servletData;

     public void init(ServletConfig config) throws ServletException {

         servletData = ServletData.get(); // singleton

     }

     @Override
     public void doGet(HttpServletRequest req, HttpServletResponse res)
             throws ServletException, IOException  {

         if (!servletData.isReady()) {

             res.sendError(503, "Put another quarter million in the slot");

         }

         // do it

     }

}

public class ServletData {

     private static Logger log = LoggerFactory.getLogger(ServletData.class);

     // calling the constructor here hangs sync on the parallel loads
     // for some reason
     private static ServletData single = null;

     public static ServletData get() {
         synchronized(ServletData.class) {
             if (single == null) {
                 single = new ServletData();
             }
         }
         return single;
     }

     private ServletData() {

             Thread th1 = new Thread(new Runnable() {
                 public void run() {
                     try {
                         approvedV =
ApprovalDao.getAllApprovedPairs(fconn, 1,
                                                      "v", null,
                                                      true, // d0
                                                      null, null,
                                                      null);
                     } catch (SQLException sqe) {
                         log.error("approvedV: " + sqe);
                         System.exit(1);
                     }
                 }
             });
             th1.start();

     }

     public isReady() {

         return approvedV != null;

     }

}

On 10/7/19 5:34 AM, Dirk Olmes wrote:

> On 10/7/19 11:21 AM, Bill Ross wrote:
>> Why not have a ContextHandler that starts a setup thread on init, and
>> answers 503 until that thread is done?
> That's sort of what I currently do (starting a setup thread from the
> main servlet's init method) but that causes all kinds of trouble because
> the servlet context accepts requests before all the app logic is ready.
>
> Based on your suggestion combined with Greg's before I came up with this
> approach: Register a ContextHandler that answers 503 and let the server
> start normally. After the server is started I launch the setup thread
> where I register the real app context with the server and manually send
> it a start(). After the context is started I unregister the
> ContextHandler that answers 503.
>
> The code is here:
> https://github.com/dirk-olmes/jetty-delayed-context-startup/tree/deferred_context_startup
>
> Ok, this approach works. But I was hoping that Jetty supported something
> like that out of the box.
>
> -dirk
> _______________________________________________
> jetty-users mailing list
> [hidden email]
> To change your delivery options, retrieve your password, or unsubscribe from this list, visit
> https://www.eclipse.org/mailman/listinfo/jetty-users
_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users
Reply | Threaded
Open this post in threaded view
|

Re: ServletContextListener defers server start

Bill Ross-2
(and return after the 503)


On 10/7/19 7:35 AM, Bill Ross wrote:

> Would anything like these chunks from my code work for you? The secret
> is checking status in doGet().
>
>
> public class GetMult extends HttpServlet {
>
>     private ServletData servletData;
>
>     public void init(ServletConfig config) throws ServletException {
>
>         servletData = ServletData.get(); // singleton
>
>     }
>
>     @Override
>     public void doGet(HttpServletRequest req, HttpServletResponse res)
>             throws ServletException, IOException  {
>
>         if (!servletData.isReady()) {
>
>             res.sendError(503, "Put another quarter million in the
> slot");
>
>         }
>
>         // do it
>
>     }
>
> }
>
> public class ServletData {
>
>     private static Logger log =
> LoggerFactory.getLogger(ServletData.class);
>
>     // calling the constructor here hangs sync on the parallel loads
>     // for some reason
>     private static ServletData single = null;
>
>     public static ServletData get() {
>         synchronized(ServletData.class) {
>             if (single == null) {
>                 single = new ServletData();
>             }
>         }
>         return single;
>     }
>
>     private ServletData() {
>
>             Thread th1 = new Thread(new Runnable() {
>                 public void run() {
>                     try {
>                         approvedV =
> ApprovalDao.getAllApprovedPairs(fconn, 1,
>                                                      "v", null,
>                                                      true, // d0
>                                                      null, null,
>                                                      null);
>                     } catch (SQLException sqe) {
>                         log.error("approvedV: " + sqe);
>                         System.exit(1);
>                     }
>                 }
>             });
>             th1.start();
>
>     }
>
>     public isReady() {
>
>         return approvedV != null;
>
>     }
>
> }
>
> On 10/7/19 5:34 AM, Dirk Olmes wrote:
>> On 10/7/19 11:21 AM, Bill Ross wrote:
>>> Why not have a ContextHandler that starts a setup thread on init, and
>>> answers 503 until that thread is done?
>> That's sort of what I currently do (starting a setup thread from the
>> main servlet's init method) but that causes all kinds of trouble because
>> the servlet context accepts requests before all the app logic is ready.
>>
>> Based on your suggestion combined with Greg's before I came up with this
>> approach: Register a ContextHandler that answers 503 and let the server
>> start normally. After the server is started I launch the setup thread
>> where I register the real app context with the server and manually send
>> it a start(). After the context is started I unregister the
>> ContextHandler that answers 503.
>>
>> The code is here:
>> https://github.com/dirk-olmes/jetty-delayed-context-startup/tree/deferred_context_startup 
>>
>>
>> Ok, this approach works. But I was hoping that Jetty supported something
>> like that out of the box.
>>
>> -dirk
>> _______________________________________________
>> jetty-users mailing list
>> [hidden email]
>> To change your delivery options, retrieve your password, or
>> unsubscribe from this list, visit
>> https://www.eclipse.org/mailman/listinfo/jetty-users
> _______________________________________________
> jetty-users mailing list
> [hidden email]
> To change your delivery options, retrieve your password, or
> unsubscribe from this list, visit
> https://www.eclipse.org/mailman/listinfo/jetty-users
>
_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users
Reply | Threaded
Open this post in threaded view
|

Re: ServletContextListener defers server start

Joakim Erdfelt-8
I went ahead and added an example to the Embedded Jetty Cookbook.


That explains how to accomplish what you need.

Joakim Erdfelt / [hidden email]


On Mon, Oct 7, 2019 at 9:36 AM Bill Ross <[hidden email]> wrote:
(and return after the 503)


On 10/7/19 7:35 AM, Bill Ross wrote:
> Would anything like these chunks from my code work for you? The secret
> is checking status in doGet().
>
>
> public class GetMult extends HttpServlet {
>
>     private ServletData servletData;
>
>     public void init(ServletConfig config) throws ServletException {
>
>         servletData = ServletData.get(); // singleton
>
>     }
>
>     @Override
>     public void doGet(HttpServletRequest req, HttpServletResponse res)
>             throws ServletException, IOException  {
>
>         if (!servletData.isReady()) {
>
>             res.sendError(503, "Put another quarter million in the
> slot");
>
>         }
>
>         // do it
>
>     }
>
> }
>
> public class ServletData {
>
>     private static Logger log =
> LoggerFactory.getLogger(ServletData.class);
>
>     // calling the constructor here hangs sync on the parallel loads
>     // for some reason
>     private static ServletData single = null;
>
>     public static ServletData get() {
>         synchronized(ServletData.class) {
>             if (single == null) {
>                 single = new ServletData();
>             }
>         }
>         return single;
>     }
>
>     private ServletData() {
>
>             Thread th1 = new Thread(new Runnable() {
>                 public void run() {
>                     try {
>                         approvedV =
> ApprovalDao.getAllApprovedPairs(fconn, 1,
>                                                      "v", null,
>                                                      true, // d0
>                                                      null, null,
>                                                      null);
>                     } catch (SQLException sqe) {
>                         log.error("approvedV: " + sqe);
>                         System.exit(1);
>                     }
>                 }
>             });
>             th1.start();
>
>     }
>
>     public isReady() {
>
>         return approvedV != null;
>
>     }
>
> }
>
> On 10/7/19 5:34 AM, Dirk Olmes wrote:
>> On 10/7/19 11:21 AM, Bill Ross wrote:
>>> Why not have a ContextHandler that starts a setup thread on init, and
>>> answers 503 until that thread is done?
>> That's sort of what I currently do (starting a setup thread from the
>> main servlet's init method) but that causes all kinds of trouble because
>> the servlet context accepts requests before all the app logic is ready.
>>
>> Based on your suggestion combined with Greg's before I came up with this
>> approach: Register a ContextHandler that answers 503 and let the server
>> start normally. After the server is started I launch the setup thread
>> where I register the real app context with the server and manually send
>> it a start(). After the context is started I unregister the
>> ContextHandler that answers 503.
>>
>> The code is here:
>> https://github.com/dirk-olmes/jetty-delayed-context-startup/tree/deferred_context_startup
>>
>>
>> Ok, this approach works. But I was hoping that Jetty supported something
>> like that out of the box.
>>
>> -dirk
>> _______________________________________________
>> jetty-users mailing list
>> [hidden email]
>> To change your delivery options, retrieve your password, or
>> unsubscribe from this list, visit
>> https://www.eclipse.org/mailman/listinfo/jetty-users
> _______________________________________________
> jetty-users mailing list
> [hidden email]
> To change your delivery options, retrieve your password, or
> unsubscribe from this list, visit
> https://www.eclipse.org/mailman/listinfo/jetty-users
>
_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users

_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users
Reply | Threaded
Open this post in threaded view
|

Re: ServletContextListener defers server start

Dirk Olmes
In reply to this post by Bill Ross-2
On 10/7/19 4:35 PM, Bill Ross wrote:
> Would anything like these chunks from my code work for you? The secret
> is checking status in doGet().

Thanks, a lot Bill. This looks quite similar to the solution I currently
have in place. However, our app consists of more than one servlet and I
had to jump through a lot of hoops to make the approach work someohw.
However, our developers are free to add more servlets to their project
and if they forget to inherit from our ready-state-checking-base-class
the door is open for all kinds of havoc.

Hence, I was looking for a more unified approach, one that does not
offer any functionality unless the context is fully up and running.

-dirk
_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users
Reply | Threaded
Open this post in threaded view
|

Re: ServletContextListener defers server start

Dirk Olmes
In reply to this post by Joakim Erdfelt-8
On 10/7/19 9:15 PM, Joakim Erdfelt wrote:
> I went ahead and added an example to the Embedded Jetty Cookbook.
>
> https://github.com/jetty-project/embedded-jetty-cookbook/blob/master/src/main/java/org/eclipse/jetty/cookbook/DelayedWebAppDeployExample.java
>
> That explains how to accomplish what you need.

Thanks, Joakim. This looks a lot like I did it in my experiments. And
this proves that there is no out of the box functionality in Jetty
currently. I will go ahead and file enhancement requests now.

-dirk
_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users