|
From: Colin S. <col...@ex...> - 2004-11-05 00:10:32
|
Just for the record though, I was being incredibly dense below, as of
course there is not even a need of the factory bean. The Communicator
itself can just be registered as the singleton.
In my own defence, I started off with another approach that did need the
factory bean. That approach was a bit more complex, but would allow a
refresh too. It's to create a MutablePropertyValue wrapping the factory
bean, and use it with a new RootBeanDefinition which is just registered
manually. Then the xml context def can also be read in. I would stick to
the simpler approach until you actually need more than one refresh though...
Venkat Sonnathi wrote:
> Hi Colin,
>
> Yes, this is what I was looking for. With the solution given below I
> don't have to write custom FactoryBean's and ApplicationContext's for
> each application object I want to expose.
>
> You guys rock!
>
> Thank you very much.
> --Venkat.
>
> From: Colin Sampaleanu <col...@ex...>
> Reply-To: spr...@li...
> To: spr...@li...
> Subject: Re: [Springframework-developer] BeanFactory partial
> pre-population with applicat
> Date: Thu, 04 Nov 2004 13:38:15 -0500
>
> Venkat,
>
> If you are willing to rely on the new GenericApplicationContext class
> which was introduced for Spring 1.1.2 (which is planned for release
> this weekend, but the code is in CVS already), there is an even easier
> mechanism.
>
> Make a simple PassthroughFactoryBean, which always returns an object
> that it was fed as a constructor:
> static class PassthroughFactoryBean implements FactoryBean {
> private Object object;
>
> public PassthroughFactoryBean(Object object) {
> this.object = object;
> }
> public Object getObject() throws Exception {
> return object;
> }
> public Class getObjectType() {
> return object.getClass();
> }
> public boolean isSingleton() {
> return true;
> }
> }
>
> now, just use GenericApplicationContext:
>
> GenericApplicationContext ctx = new GenericApplicationContext();
> ConfigurableListableBeanFactory factory = ctx.getBeanFactory();
>
> PassthroughFactoryBean communicatorFactory = new
> PassthroughFactoryBean(communicator);
> factory.registerSingleton("communicator", communicator);
> XmlBeanDefinitionReader xmlReader = new
> XmlBeanDefinitionReader(ctx);
> xmlReader.loadBeanDefinitions(new
> ClassPathResource(contextFileLocation));
> ctx.refresh();
>
> And after writing this, I just realized that even with a normal
> ClasspathXmlApplicationContext, what you should be able to do is just
> use the constructor with refresh=false to create the context but not
> initialize it yet, then just add the singleton factory bean exactly as
> above, then call refresh on it. Just be careful, as a subsequent
> refresh will not have the manually added singleton bean! That's why
> GenericApplicationContext doesn't even allow more than one refresh.
>
> Colin
>
>
> Venkat Sonnathi wrote:
>
>> Hi Colin,
>>
>> Thanks for the solution, that was quite descriptive. As you said it
>> took me 10 min to implement.
>>
>> It would be nice to have a generic mechanism that is part of the
>> framework that will do the same, probably the requrement is not too
>> common to warrant that.
>>
>> Thanks again,
>> --Venkat.
>>
>>
>>
>> From: Colin Sampaleanu <col...@ex...>
>> Reply-To: spr...@li...
>> To: spr...@li...
>> Subject: Re: [Springframework-developer] BeanFactory partial
>> pre-population with application objects.
>> Date: Tue, 02 Nov 2004 16:56:10 -0500
>>
>> There's probably some cleaner ways to handle this, but off the top of
>> my head I can think of one fairly easy mechanism that should take 10
>> minutes or less to implement.
>>
>> Sucblass ClasspathXmlApplicationContext to have a Communicator field,
>> and getCommunicator() method to get the value of this. When your
>> variant of ClasspathXmlApplicationContext is created, the
>> Communicator instance could be passed in as a constructor arg (make a
>> new constructor), or as a setter property (you would need to make
>> sure to use the existing constructor with refresh=false, for that
>> approach). To actually get at the Communicator instance inside the
>> context def, the user would just use a custom FactoryBean you define.
>> This factory bean would be ApplicationContextAware, so would have the
>> context given to it. All it would do on the getObject() method, is
>> cast the context to your subclass type, and return the value of the
>> getCommunicator() method. All the user has to do when setting up
>> their context.xml file is remember to add in a one line bean
>> definition for your factory:
>>
>> <bean id="communicator" class="x.y.z.CommunicatorFactoryBean"/>
>>
>>
>> Regards,
>> Colin
>>
>> Venkat Sonnathi wrote:
>>
>>> Hi,
>>>
>>> The subject may sound strange but please bear with me. I am trying
>>> to use Spring to isolate ICE (http://www.zeroc.com) specific
>>> depedencies. I could prototype the client side interaction (Thanks
>>> to Jurgen for pointing me in the right direction), but have come to
>>> a block when trying Server side.
>>>
>>> ICE has a kind of app server called IceBox, it loads different
>>> services from a Config file, it has a feature called
>>> UseSharedCommunicator, which means all the loaded services share the
>>> same ICE runtime instance and calls to other services located in the
>>> same instance are treated as local calls.
>>>
>>> Basically you wrap a ServiceImpl class in ServiceAdapter so that
>>> IceBox can load it, here is an example of the ServiceAdapter for a
>>> ServiceImpl class PrinterI
>>>
>>> public class IceBoxService extends Ice.LocalObjectImpl implements
>>> IceBox.Service {
>>>
>>> private Ice.ObjectAdapter adapter;
>>>
>>> public void start(String s, Communicator communicator,
>>> String[] strings) {
>>>
>>> this.adapter = communicator.createObjectAdapter(s);
>>> Ice.Object object = new PrinterI(communicator);
>>> adapter.add(object,
>>> Ice.Util.stringToIdentity("SimpleFCASearch"));
>>> adapter.activate();
>>> }
>>>
>>> public void stop() {
>>> adapter.deactivate();
>>> }
>>> }
>>>
>>> }
>>>
>>> I was planning on writing a generic IceBoxService which takes a
>>> parameter to context.xml file and instantiate a BeanFactory which
>>> loads the ServiceImpls and resolve the services they depend upon.
>>> But, if you observe how the PrinterI is instantiated, the
>>> communicator instance passed to it should be one that is supplied by
>>> the IceBox server (passed in as a parameter to start method). How to
>>> make a bean factory aware of this communicator?
>>>
>>> The following code explains the behaviour I am looking for:
>>> BeanFactory bf = new ClassPathXmlApplicationContext();
>>> bf.setBean("communicator", communicator); // Setting/passing the
>>> application communicator instance to the Bean
>>> bf.load("context.xml"); // refers to the communicator bean passed in
>>> above statement.
>>>
>>> Thanks for your time and patience.
>>>
>>> --Venkat.
>>>
|