BusConfiguratorFeature

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

BusConfiguratorFeature

Ranx0r0x

I've been creating a BusConfiguratorFeature to be able to consolidate the setup of features, interceptors, etc. in a single bundle and then apply this to the CXF Bus of a given name when it gets registered. Invariably developers at organizations I go to spam configuration and set up of busses across all their bundles.

 

Basically it is address this issue:

https://cwiki.apache.org/confluence/display/CXF/Grouping+bundles+to+applications+in+OSGi

 

I'm rarely at a client's site where the setup of services across bundles is identical. Different department, software stacks, etc. all seem to have different flavors. The issue with the way Features work is that when you install it, it is applied to every CXF Bus instance that gets created.

 

Basically I'm piggybacking on that and creating an internal registry/Map of bus id to bus configuration object. I also have some mixins that allow for some pluggable behavior. This works well but I'm not entirely happy with it as implementing the Feature gets a lot of notifications I don't really care about (for example, client, provider, server, etc.) and just leave them blank right now.

 

This let's me as coarse or granular in the configuration as I want. I set these up in Blueprint as most of the different setups for things like JAASAuthenticationFeature or as simple as logging providers are in Blueprint or at least most examples are.

 

I was thinking about re-implementing the BusConfiguratorFeature as a DS component that would listen for BusConfigurationBeans and add/remove/update them from the registry and listen for Bus registration and apply configurations, if any, are applicable, when it is received. I've used DS in the past but usually it is simple @Reference injection and service export.

In this case I'd need a component that would listen for BusConfigurationBeans and add/update the registry and also listen for Bus registration and apply the configurations - but I don't need to keep the Bus in a list. It wouldn't be stateful.

 

Are there any good examples, perhaps from PAX or Karaf projects themselves, where I might get a good sample?

 

public class BusConfiguratorFeature extends WebServiceFeature implements Feature {

 

               

                //Avoid nulls...

                private Map<String, BusConfiguratorBean> configuratorRegistry = new HashMap<String,BusConfiguratorBean>();

 

 

                public void setConfigurators(Map<String, BusConfiguratorBean>

configurators) {

                                this.configuratorRegistry = configurators;

                                               

                }

//Basically this is the only even I really want notification about.

                @Override

                public void initialize(Bus bus) {

                                BusConfiguratorBean configurator = configuratorRegistry.get(bus.getId());

                                if(configurator!=null)

                                                configurator.setBus(bus);

 

                }

//The configurator bean.

public class BusConfiguratorBean {

 

                /** The interceptorProviders. */

                private List<InterceptorProvider> interceptorProviders = new ArrayList<InterceptorProvider>();

                private List<Feature> features = new ArrayList<Feature>();

 

                private Map<String, Object> properties = new HashMap<String,Object>();

 

                public void setBus(Bus bus) {

 

                                                for (InterceptorProvider provider : interceptorProviders) {

                                                                bus.getInFaultInterceptors().addAll(provider.getInFaultInterceptors());

                                               

bus.getOutFaultInterceptors().addAll(provider.getOutFaultInterceptors());

                                                                bus.getInInterceptors().addAll(provider.getInInterceptors());

                                                                bus.getOutInterceptors().addAll(provider.getOutInterceptors());

 

                                                }

                                                bus.getFeatures().addAll(features);

                                                bus.setProperties(this.properties);

                               

                                                //System.out.println("The rolled up properties: "+ bus.getProperties());

                               

                }

 

public class BusConfigurationMixin implements InterceptorProvider {

 

                protected ModCountCopyOnWriteArrayList<Interceptor&lt;? extends Message>> inInterceptors = new ModCountCopyOnWriteArrayList<Interceptor&lt;? extends

Message>>();

                protected ModCountCopyOnWriteArrayList<Interceptor&lt;? extends Message>> outInterceptors = new ModCountCopyOnWriteArrayList<Interceptor&lt;? extends

Message>>();

                protected ModCountCopyOnWriteArrayList<Interceptor&lt;? extends Message>> outFaultInterceptors = new ModCountCopyOnWriteArrayList<Interceptor&lt;?

extends Message>>();

                protected ModCountCopyOnWriteArrayList<Interceptor&lt;? extends Message>> inFaultInterceptors = new ModCountCopyOnWriteArrayList<Interceptor&lt;?

extends Message>>();

                protected Map<String,Object> properties = new HashMap<String,Object>();

 

 

Reply | Threaded
Open this post in threaded view
|

Re: BusConfiguratorFeature

Ranx0r0x
I have the DS component straightened out now. I listen for CXF Bus
registrations and have a separate interface that can be used to add
BusConfiguration instances to the registry. Commonly I'm using the same
configuration object across multiple busses so it doesn't degrade into high
complexity unnecessarily but it is easy enough to create instances.

Anything I'm missing here?

This isn't just about the difference in endpoints in production either, it's
about being able to easily switch the Bus from a development to production.
A lot of time when I'm working on new functionality and integration, I don't
want to be fooling with security or such issues but I do want to log
everything going in and out. In production it is usually a security
violation to be logging all incoming and outgoing data.

So I can have a mixin that logs everything. The Feature works fine for this
but it really isn't intended functionality. Now it is a component that lives
in its own bundle and the configuration info below will pull that interface
from the registry and add the configurators that way instead of directly
instantiating and exporting to the registry.

        <bean id="configFeatureListener"
class="foo.esb.cxf.bus.configuration.internal.BusConfiguratorFeature">
  <property name="configurators">
                                <map>
                                        <entry key="fooBus" value-ref="developmentBusConfiguration" />
                                        <entry key="barBus" value-ref="developmentBusConfiguration" />
                                        <entry key="bazBus" value-ref="standardProductionBusConfiguration" />

                                </map>
                        </property>
  </bean>


        <bean id="developmentBusConfiguration"
class=foo.esb.cxf.bus.configuration.internal.BusConfiguratorBean">
                <property name="mixins">
                        <list>
                                <ref component-id="commons" />
                                <ref component-id="debugLogging" />

                        </list>
                </property>
               
                <property name="properties">
                        <map>
                                <entry key="someKey" value="A property override in standard bus." />

                        </map>
                </prop

<!--Different blueprint file for just different logging setups -->

        <bean id="logInbound"
class="org.apache.cxf.interceptor.LoggingInInterceptor" />
        <bean id="logOutbound"
class="org.apache.cxf.interceptor.LoggingOutInterceptor" />

        <bean id="debugLogging"
class="gov.texas.trs.esb.cxf.bus.configuration.internal.BusConfigurationMixin">

                <property name="inInterceptors">
                        <list>
                                <ref component-id="logInbound" />
                        </list>
                </property>
                <property name="outInterceptors">
                        <list>
                                <ref component-id="logOutbound" />
                        </list>
                </property>

        </bean>



--
Sent from: http://karaf.922171.n3.nabble.com/Karaf-User-f930749.html
Reply | Threaded
Open this post in threaded view
|

Re: BusConfiguratorFeature

Ranx0r0x
In reply to this post by Ranx0r0x

Would this question be more appropriate on a different forum? Like one for
CXF?



--
Sent from: http://karaf.922171.n3.nabble.com/Karaf-User-f930749.html
Reply | Threaded
Open this post in threaded view
|

Re: BusConfiguratorFeature

Ranx0r0x
In reply to this post by Ranx0r0x
Perhaps the Karaf user's forum isn't the right place for this but I thought
I'd at least show what I have  and see if there's any interest. If this were
hardened a bit more I think it would be a great mechanism for OSGi. I've
installed and tested it via features files and it seems to work fine.

I now have a new bundle with a DS component that listens for Bus and
BusConfigurator interfaces. The BusConfigurator contains a
Map<String,BusConfiguratorBean> which is keyed by bus id to a
BusConfiguratorBean. The BusConfiguratorBeans are basically like a Feature
implementation with interceptors, features, properties. A
BusConfiguratorBean can be associated with 1...N Bus ids in the map. In
other words, while it allows for a great deal of granularity it can also be
a coarser granularity - if 80% of your web services have identical security,
logging, features, etc. they'd all use the same BusConfiguratorBean, that
is, the same BusConfiguratorBean would be added to the map keyed by
different bus ids.

If a Bus comes in that doesn't have a configurator associated with its id,
it is parked in the the unconfigured bus registry. If a configurator is
later added, that configuration is applied to the Bus. So there's a bit of
temporal decoupling.

The one thing this will not do is /update/and already configured Bus. in
other words, if a Bus/BusConfiguratorBean are paired and the Bus gets
configured but in the future a new BusConfiguratorBean for that Bus comes
in, this doesn't reconfigure the existing Bus. I certainly could keep the
busses in a map and do such reconfiguration but I'd have to be a lot clearer
about the mechanics and implications of that. For my use case, that's not
really too important.

The intended use case is to provide a mechanism to (a) avoid duplication of
bus configurations, (b) provide a high degree of reuse, (c) provide high
customization, (d) consolidate Bus configurations into a single bundle, and
(e) easily support microservices like installation of webservices.

So my intended use case is that the bus configurators would get installed
early. As webservices get installed and uninstalled it tracks them and
configures them as necessary. While the configurators could be updated after
that and would configure any new webservices installed, it isn't anticipated
to be the common use case.

While I use DS as often as possible, I'm not as conversant as I'd like. Are
there any issues with the way I have the listener mechanisms set up with
dynamic and greedy?






--
Sent from: http://karaf.922171.n3.nabble.com/Karaf-User-f930749.html