You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@karaf.apache.org by Steinar Bang <sb...@dod.no> on 2020/08/29 16:41:57 UTC

Is it possible to activate a DS component only when an HTTP request is completed?

Is it possible to have a DS component to only go active when an HTTP
request is successfully completed?

Here is what I want to do:
 1. Have a DS component that exposes a service of type PreHook
 2. The PreHook service is picked up by jdbc-config and is used to
    create a schema in a JDBC database and populate the database with
    initial data
 3. The DS component does an HTTP call to get a liquibase changeset
    containing data for the database
 4. If the HTTP call fails for some reason (wrong URL, No URL, server
    not responding, server responding with error code etc.) I would like
    the DS component to log the reason for failing but not go ACTIVE

Is this possible?  Recommended?  Not recommended?

It's OK for me if this DS component won't automatically restart, because
a failure in loading the URL will be so drastic that I might as well
restart the world (ie. restart karaf).

Thanks!


- Steinar


Re: Is it possible to activate a DS component only when an HTTP request is completed?

Posted by Tim Ward <ti...@paremus.com>.
If you’re stuck with the async startup then the best way to approach this sort of thing is to take the “service” bit out of the component and manage the service registration lifecycle yourself. It is much less pretty, but at least DS can manage the service and configuration dependencies for you.

@Component
public class MyComponent {

  AtomicBoolean active = new AtomicBoolean(false);
  AtomicReference<ServiceRegistration<MyService>> reg = new AtomicReference<>();

  @Reference
  MyDependency myDep;

  @Activate
  BundleContext ctx;
  
  @Activate
  Map<String, Object> config;

  @Activate
  void start() {
    active.set(true);
    new Thread(this::asyncStart).run();
  }

  void asyncStart() {
    MyServiceImpl impl = new MyServiceImpl(myDep);
    impl.longRunningSetup();
    If(active.get()) {
      reg.set(ctx.registerService(MyService.class, impl, new Hashtable(config)));
      if(!active.get()) {
        ServiceRegistration sReg = reg.getAndSet(null);
        if(sReg != null) { sReg.unregister(); }
      }
    }
  }

  @Deactivate
  Void stop() {
    active.set(false);
    ServiceRegistration sReg = reg.getAndSet(null);
    if(sReg != null) { sReg.unregister(); }
  }
}


Tim

> On 29 Aug 2020, at 20:16, Steinar Bang <sb...@dod.no> wrote:
> 
>>>>>> Steinar Bang <sb...@dod.no>:
>> Or maybe I don't have to involve the PreHook at all?
> 
>> The data liquibase file doesn't have to be loaded at the same time as
>> the schema, it can be loaded later.
> 
>> But: the schema must be in place before the data is attempted loaded.
> 
> Not a problem: I can create a separate DS component that listens for the
> DataSource produced by jdbc-config, because that won't become active
> until after the PreHook has done its job.
> 


Re: Is it possible to activate a DS component only when an HTTP request is completed?

Posted by Steinar Bang <sb...@dod.no>.
>>>>> Steinar Bang <sb...@dod.no>:
> Or maybe I don't have to involve the PreHook at all?

> The data liquibase file doesn't have to be loaded at the same time as
> the schema, it can be loaded later.

> But: the schema must be in place before the data is attempted loaded.

Not a problem: I can create a separate DS component that listens for the
DataSource produced by jdbc-config, because that won't become active
until after the PreHook has done its job.


Re: Is it possible to activate a DS component only when an HTTP request is completed?

Posted by Steinar Bang <sb...@dod.no>.
>>>>> Jean-Baptiste Onofre <jb...@nanthrax.net>:

> I don’t think it’s possible and I don’t think it’s a good idea to do
> that with SCR. The component state is evaluate at activate.

Right, so when the activate method is called it's already too late?

I guess that pulls the rug under the suggestion I had in my other
reply...?

> I would rather create a custom controller service acting as a service
> factory when the HTTP requests come.

Hm... but doesn't that just push the problem to the custom controller
service...?

What I want (I think), is to somehow delay the PreHook service until I
have a liquibase ChangeLog

Or maybe I don't have to involve the PreHook at all?

The data liquibase file doesn't have to be loaded at the same time as
the schema, it can be loaded later.

But: the schema must be in place before the data is attempted loaded.

Hmm.. I need to rethink this.

In any case, messing with the DS activation is a bad idea.

Thanks to both!


Re: Is it possible to activate a DS component only when an HTTP request is completed?

Posted by Jean-Baptiste Onofre <jb...@nanthrax.net>.
Hi Steinar,

I don’t think it’s possible and I don’t think it’s a good idea to do that with SCR. The component state is evaluate at activate.

I would rather create a custom controller service acting as a service factory when the HTTP requests come.

Regards
JB

> Le 29 août 2020 à 18:41, Steinar Bang <sb...@dod.no> a écrit :
> 
> Is it possible to have a DS component to only go active when an HTTP
> request is successfully completed?
> 
> Here is what I want to do:
> 1. Have a DS component that exposes a service of type PreHook
> 2. The PreHook service is picked up by jdbc-config and is used to
>    create a schema in a JDBC database and populate the database with
>    initial data
> 3. The DS component does an HTTP call to get a liquibase changeset
>    containing data for the database
> 4. If the HTTP call fails for some reason (wrong URL, No URL, server
>    not responding, server responding with error code etc.) I would like
>    the DS component to log the reason for failing but not go ACTIVE
> 
> Is this possible?  Recommended?  Not recommended?
> 
> It's OK for me if this DS component won't automatically restart, because
> a failure in loading the URL will be so drastic that I might as well
> restart the world (ie. restart karaf).
> 
> Thanks!
> 
> 
> - Steinar
> 


Re: Is it possible to activate a DS component only when an HTTP request is completed?

Posted by Steinar Bang <sb...@dod.no>.
>>>>> Steinar Bang <sb...@dod.no>:

> How about:
>  1. Starting the HTTP request in a separate thread from the constructor
>     of the DS component and clearing a semaphore if and only if, the
>     HTTP request is successfully completed
>  2. Let the activate method of the DS component block on the semaphore
>     and only complete if the semaphore is released
> ?

Ok, based on what JP said, this is also a no-go because by the time the
activate method is called the component is assumed to be active, so
blocking here won't help anything.

PS Thanks for your reply, David (I forgot say that)



Re: Is it possible to activate a DS component only when an HTTP request is completed?

Posted by Steinar Bang <sb...@dod.no>.
>>>>> David Jencks <da...@gmail.com>:

> I don’t understand the relationship between the DS component and the
> jdbc-config.  Is the DS component configured so that when it’s
> activated it knows how to do the http call, and then when the
> jdbc-config calls it it already has the desired information?

That was my intent, yes.

> If that is the case, you could perhaps have the DS component not
> expose the prehook service but rather do the http call (in a separate
> thread, please, to not delay other startup) and if successful register
> the preHook service “by hand”.

Hm... maybe...?

How about:
 1. Starting the HTTP request in a separate thread from the constructor
    of the DS component and clearing a semaphore if and only if, the
    HTTP request is successfully completed
 2. Let the activate method of the DS component block on the semaphore
    and only complete if the semaphore is released
?


Re: Is it possible to activate a DS component only when an HTTP request is completed?

Posted by David Jencks <da...@gmail.com>.
I think this is impossible, and it’s certainly a bad idea.  The active state of a DS service depends on the “service environment” it’s in, and whether an instance of the component can actually be successfully activated is irrelevant.  Normally DS components exposing services are delayed, so the component is active and the service is registered before any instances are created.  Also, component activations are supposed to be quick, and making remote calls may lead to timeout issues.

I don’t understand the relationship between the DS component and the jdbc-config.  Is the DS component configured so that when it’s activated it knows how to do the http call, and then when the jdbc-config calls it it already has the desired information?  If that is the case, you could perhaps have the DS component not expose the prehook service but rather do the http call (in a separate thread, please, to not delay other startup) and if successful register the preHook service “by hand”.

David Jencks

> On Aug 29, 2020, at 9:41 AM, Steinar Bang <sb...@dod.no> wrote:
> 
> Is it possible to have a DS component to only go active when an HTTP
> request is successfully completed?
> 
> Here is what I want to do:
> 1. Have a DS component that exposes a service of type PreHook
> 2. The PreHook service is picked up by jdbc-config and is used to
>    create a schema in a JDBC database and populate the database with
>    initial data
> 3. The DS component does an HTTP call to get a liquibase changeset
>    containing data for the database
> 4. If the HTTP call fails for some reason (wrong URL, No URL, server
>    not responding, server responding with error code etc.) I would like
>    the DS component to log the reason for failing but not go ACTIVE
> 
> Is this possible?  Recommended?  Not recommended?
> 
> It's OK for me if this DS component won't automatically restart, because
> a failure in loading the URL will be so drastic that I might as well
> restart the world (ie. restart karaf).
> 
> Thanks!
> 
> 
> - Steinar
>