[xwiki-devs] Problems accessing DocumentAccessBridge from the XWiki implementation for Shindig PersonService
Hi, In order to integrate Shindig with the XWiki datastore, 4 interfaces have to be implemented: PersonService, AppDataService, ActivityService and MessagesService (javadocs here [0]). To this end, I have created the xwiki-social-opensocial module [1]. While implementing PersonService (PersonServiceXW - [2]), I have encountered the following problem: As I needed to access the datastore, I also made PersonServiceXW a XWiki Component in order to gain access to the DocumentAccessBridge Component. BUT, here is the problem, the DocumentAccessBridge never gets initialized and at runtime is null. The reason this might happen, as Sergiu suggested, is that Shindig uses Guice to bind the services implementations in its code, thus the PersonServiceXW component never gets to be registered with XWiki's Component Manager. My question is how do I get data in and out XWiki's datastore from the PersonService implementation, if I cannot use the DocumentAccessBridge this way? Can it be registered to the Component Manager somehow, or is there a completely different way this could be achieved? I will continue with some integration details (about the patch on xwiki-web-standard and the OpenSocial XWiki Application). At the end I included some instructions on how to build and test them. ***xwiki-web-standard patch (apply on xwiki-platform-web), consisting of: - in standard/src/main/webapps/templates: * added 3 .vm files which handles getting/adding/deleting friends: addfriend.vm, getuserfriends.vm, deletefriend.vm - in standard/src/main/webapps/resources/xwiki/opensocial: * added javascript and css files necessary for the Shindig container - in standard/src/main/webapps/WEB-INF: * modified web.xml to include all shindig servlet mappings and necessary Guice modules - in standard/src/main/webapps/WEB-INF/classes: * added container/default/container.js and shindig.properties - default Shindig container configurations. I put them in the classpath as they required modifications from the original files - in standard: * modified pom.xml, to include as a dependency xwiki-social-opensocial module ***Open Social XWiki Application, consisting of: - OpenSocial.GadgetContainerClass - the simplest OpenSocial Gadget container; has a single url property (the url of the gadget); in view mode it displays/renders it - OpenSocial.GadgetContainerClassSheet - OpenSocial.GadgetContainerClassTemplate - OpenSocial.HelloWorld - hello world Gadget (only displays a String) - NO OpenSocial features - works - OpenSocial.LabpixiesTodo - Gadget with NO OpenSocial features 1 - works - OpenSocial.Horoscope - Gadget with NO OpenSocial features 2 - works - OpenSocial.ListFriends - SHOULD list the friends of the currently logged in user. The friends are retrieved using the XWiki implementation of the Shindig's PersonService, which is located in the xwiki-social-opensocial module (PersonServiceXW). The service TRIES to use DocumentAccessBridge component in order to retrieve the necessary data from the XWiki datastore. - OpenSocial.TestingGadgetsSource - used to attach gadgets XML files to the page. Their URLs can be used for GadgetContainerClass objects (e.g. ListFriends gadget) - Panels.My Friends - panel, displays the friends of the currently logged in user - Panels.Navigation - XWiki.FriendClass - A friend; objects of this type can be attached to user profiles; has as a single property friendName, which contains the name of the friend - XWiki.FriendClassSheet - XWiki.FriendClassTemplate - XWiki.XWikiUserSheet - to add the list of friends to profile - XWiki.MyResources - XWiki.XWikiPreferences Instructions for testing (one possible way at least): 1. Patch xwiki-platform-web (changes are only in xwiki-web-standard), with the patch from JIRA - [3] 2. Build xwiki-web-standard 3. Build xwiki-enterprise in offline mode (-o), so it will use xwiki-web-standard from the local repository build at step 2 4. Run XWiki Enterprise. I always use xwiki-enterprise-jetty-hsqldb-2.0-SNAPSHOT from the generated distributions 5. Import opensocial XAR - [4] What to look for while testing (working stuff): - Gadgets: - see all/add new gadgets http://localhost:8080/xwiki/bin/view/OpenSocial/GadgetContainerClass - http://localhost:8080/xwiki/bin/view/OpenSocial/HelloWorld - http://localhost:8080/xwiki/bin/view/OpenSocial/LabpixiesTodo - http://localhost:8080/xwiki/bin/view/OpenSocial/Horoscope - http://localhost:8080/xwiki/bin/view/OpenSocial/ListFriends (social features) --> as specified before, not working - While you're here, you could also: - Log in as Alice (password 'alice') - Go to profile page and edit friends list; You should have 2 friends: Jane and Bob (they have as passwords 'jane', and 'bob') - See My Friends Panel, with the friends of the current logged in user displayed [0] - http://incubator.apache.org/shindig/shindig-1.1.x/apidocs/org/apache/shindig... [1] - https://svn.xwiki.org/svnroot/xwiki/sandbox/gsoc/opensocial/xwiki-social-ope... [2] - https://svn.xwiki.org/svnroot/xwiki/sandbox/gsoc/opensocial/xwiki-social-ope... [3] - http://jira.xwiki.org/jira/browse/XSANDBOX-36?focusedCommentId=43674&page=co... [4] - http://jira.xwiki.org/jira/browse/XSANDBOX-64?focusedCommentId=43675&page=co... Other helpful links: - Guice module configuration for my service implementations https://svn.xwiki.org/svnroot/xwiki/sandbox/gsoc/opensocial/xwiki-social-ope... - Exemple of PersonService being injected by Guice in Shindig's code http://svn.apache.org/repos/asf/incubator/shindig/trunk/java/social-api/src/... Thanks, Anamaria
Hi Anamaria, On Aug 9, 2009, at 2:39 AM, Anamaria Stoica wrote:
Hi,
In order to integrate Shindig with the XWiki datastore, 4 interfaces have to be implemented: PersonService, AppDataService, ActivityService and MessagesService (javadocs here [0]). To this end, I have created the xwiki-social-opensocial module [1].
While implementing PersonService (PersonServiceXW - [2]), I have encountered the following problem: As I needed to access the datastore, I also made PersonServiceXW a XWiki Component in order to gain access to the DocumentAccessBridge Component. BUT, here is the problem, the DocumentAccessBridge never gets initialized and at runtime is null.
The reason this might happen, as Sergiu suggested, is that Shindig uses Guice to bind the services implementations in its code, thus the PersonServiceXW component never gets to be registered with XWiki's Component Manager.
There's no magic. If the component is registered in components.txt and if you're looking it up to access it the DAB will get set properly. So it's just that you're no looking it up and there's no way it can be injected with dependencies.
My question is how do I get data in and out XWiki's datastore from the PersonService implementation, if I cannot use the DocumentAccessBridge this way?
Why couldn't you use it?
Can it be registered to the Component Manager somehow, or is there a completely different way this could be achieved?
You're not provided enough information so that we can help you. From what I read the solution is extra simple: just look up the component using XWiki's component manager and you're done. Now the only question is what shinding requires. Does it accept an instance of PersonService or does it take a class. In other words does it perform the instantiation itself (the new) or can you pass to it an already instantiated object? *IF* (and if) it controls the instantiation then you need to do it differently: - knowing guice you can configure if to inject an instance instead of a class so that might be a direction to look into - otherwise simply make you person service impl a standard POJO and have a setDAB method that you call after it's been instantiated by shindig somehow. [snip] Thanks -Vincent
Hi, Thanks for the reply. I added more details to my question. (message bellow) On Sun, Aug 9, 2009 at 11:49 AM, Vincent Massol <[email protected]> wrote:
Hi Anamaria,
On Aug 9, 2009, at 2:39 AM, Anamaria Stoica wrote:
Hi,
In order to integrate Shindig with the XWiki datastore, 4 interfaces have to be implemented: PersonService, AppDataService, ActivityService and MessagesService (javadocs here [0]). To this end, I have created the xwiki-social-opensocial module [1].
While implementing PersonService (PersonServiceXW - [2]), I have encountered the following problem: As I needed to access the datastore, I also made PersonServiceXW a XWiki Component in order to gain access to the DocumentAccessBridge Component. BUT, here is the problem, the DocumentAccessBridge never gets initialized and at runtime is null.
The reason this might happen, as Sergiu suggested, is that Shindig uses Guice to bind the services implementations in its code, thus the PersonServiceXW component never gets to be registered with XWiki's Component Manager.
There's no magic. If the component is registered in components.txt and if you're looking it up to access it the DAB will get set properly. So it's just that you're no looking it up and there's no way it can be injected with dependencies.
The component is registered in components.txt, see https://svn.xwiki.org/svnroot/xwiki/sandbox/gsoc/opensocial/xwiki-social-ope.... I'm not sure how I am supposed to look my component up, I mean where. I do look up DAB from my component, but not my component from another place.
My question is how do I get data in and out XWiki's datastore from the PersonService implementation, if I cannot use the DocumentAccessBridge this way?
Why couldn't you use it?
I did manage to use it with the @Requirement annotation, but as I said, it's null.
Can it be registered to the Component Manager somehow, or is there a completely different way this could be achieved?
You're not provided enough information so that we can help you.
From what I read the solution is extra simple: just look up the component using XWiki's component manager and you're done.
OK, I tried this with the following code: EmbeddableComponentManager ecm = new EmbeddableComponentManager(); ecm.initialize(this.getClass().getClassLoader()); documentAccessBridge = ecm.lookup(DocumentAccessBridge.class); if (!documentAccessBridge.exists("XWiki.Julia")) { do smth } But I get a NPE when trying to get the context from DefaultExtension: java.lang.NullPointerException at org.xwiki.context.internal.DefaultExecution.getContext(DefaultExecution.java:67) at com.xpn.xwiki.doc.DefaultDocumentAccessBridge.getContext(DefaultDocumentAccessBridge.java:58) at com.xpn.xwiki.doc.DefaultDocumentAccessBridge.exists(DefaultDocumentAccessBridge.java:148) (see full stacktrace here http://ana-s-private-labs.pastebin.com/m655cdf70)
Now the only question is what shinding requires. Does it accept an instance of PersonService or does it take a class. In other words does it perform the instantiation itself (the new) or can you pass to it an already instantiated object?
It looks like you can bind an instance to type in Guice. This is done either with Instance Bindings, @Provides Methods or Provider Bindings, depending on the complexity of the class. (http://code.google.com/p/google-guice/wiki/Bindings) All bindings are defined in a class that extends AbstractModule, this would be XWSocialModule in my code ( https://svn.xwiki.org/svnroot/xwiki/sandbox/gsoc/opensocial/xwiki-social-ope...). These modules are then passed as arguments to Guice.createInjector(), which builds the injector. In my application, the injector is build by GuiceServletContextListener ( http://svn.apache.org/repos/asf/incubator/shindig/trunk/java/common/src/main...) This servlet takes the context parameters defined in my web.xml; these are: <context-param> <param-name>guice-modules</param-name> <param-value> org.apache.shindig.common.PropertiesModule: org.apache.shindig.gadgets.DefaultGuiceModule: org.apache.shindig.gadgets.oauth.OAuthModule: org.apache.shindig.common.cache.ehcache.EhCacheModule: org.xwiki.opensocial.social.XWSocialModule </param-value> </context-param> <listener> <listener-class>org.xwiki.container.servlet.XWikiServletContextListener</listener-class> </listener> Now, all I need to do is bind the instance of PersonServiceXW after it has been initialized by XWiki's Component Manager. The binding will be done in XWSocialModule, using one of the instance binding methods (Instance Bindings, @Provides Methods or Provider Bindings). My questions are: 1. How do I make sure PersonServiceXW has been initialized already by the XWiki CM before binding it for Guice ? 2. How do I get the initialized PersonServiceXW instance from XWSocialModule ?
*IF* (and if) it controls the instantiation then you need to do it differently: - knowing guice you can configure if to inject an instance instead of a class so that might be a direction to look into - otherwise simply make you person service impl a standard POJO and have a setDAB method that you call after it's been instantiated by shindig somehow.
[snip]
Thanks -Vincent
_______________________________________________ devs mailing list [email protected] http://lists.xwiki.org/mailman/listinfo/devs
Thanks a lot, Anamaria
Anamaria Stoica wrote:
It looks like you can bind an instance to type in Guice. This is done either with Instance Bindings, @Provides Methods or Provider Bindings, depending on the complexity of the class. (http://code.google.com/p/google-guice/wiki/Bindings)
All bindings are defined in a class that extends AbstractModule, this would be XWSocialModule in my code ( https://svn.xwiki.org/svnroot/xwiki/sandbox/gsoc/opensocial/xwiki-social-ope...).
These modules are then passed as arguments to Guice.createInjector(), which builds the injector. In my application, the injector is build by GuiceServletContextListener ( http://svn.apache.org/repos/asf/incubator/shindig/trunk/java/common/src/main...) This servlet takes the context parameters defined in my web.xml; these are:
<context-param> <param-name>guice-modules</param-name> <param-value> org.apache.shindig.common.PropertiesModule: org.apache.shindig.gadgets.DefaultGuiceModule: org.apache.shindig.gadgets.oauth.OAuthModule: org.apache.shindig.common.cache.ehcache.EhCacheModule: org.xwiki.opensocial.social.XWSocialModule </param-value> </context-param>
<listener>
<listener-class>org.xwiki.container.servlet.XWikiServletContextListener</listener-class> </listener>
Now, all I need to do is bind the instance of PersonServiceXW after it has been initialized by XWiki's Component Manager. The binding will be done in XWSocialModule, using one of the instance binding methods (Instance Bindings, @Provides Methods or Provider Bindings).
My questions are: 1. How do I make sure PersonServiceXW has been initialized already by the XWiki CM before binding it for Guice ?
List GuiceServletContextListener AFTER XWikiServletContextListener in web.xml. The servlet spec specifies that listeners are called in the order they are encountered in web.xml, and XWikiServletContextListener is the one that starts our component manager.
2. How do I get the initialized PersonServiceXW instance from XWSocialModule?
com.xpn.xwiki.web.Utils.getComponent(PersonServiceXW.class) -- Sergiu Dumitriu http://purl.org/net/sergiu/
On Aug 10, 2009, at 12:41 PM, Sergiu Dumitriu wrote:
Anamaria Stoica wrote:
It looks like you can bind an instance to type in Guice. This is done either with Instance Bindings, @Provides Methods or Provider Bindings, depending on the complexity of the class. (http://code.google.com/p/google-guice/wiki/Bindings)
All bindings are defined in a class that extends AbstractModule, this would be XWSocialModule in my code ( https://svn.xwiki.org/svnroot/xwiki/sandbox/gsoc/opensocial/xwiki-social-ope...) .
These modules are then passed as arguments to Guice.createInjector(), which builds the injector. In my application, the injector is build by GuiceServletContextListener ( http://svn.apache.org/repos/asf/incubator/shindig/trunk/java/common/src/main...) This servlet takes the context parameters defined in my web.xml; these are:
<context-param> <param-name>guice-modules</param-name> <param-value> org.apache.shindig.common.PropertiesModule: org.apache.shindig.gadgets.DefaultGuiceModule: org.apache.shindig.gadgets.oauth.OAuthModule: org.apache.shindig.common.cache.ehcache.EhCacheModule: org.xwiki.opensocial.social.XWSocialModule </param-value> </context-param>
<listener>
<listener- class>org.xwiki.container.servlet.XWikiServletContextListener</ listener-class> </listener>
Now, all I need to do is bind the instance of PersonServiceXW after it has been initialized by XWiki's Component Manager. The binding will be done in XWSocialModule, using one of the instance binding methods (Instance Bindings, @Provides Methods or Provider Bindings).
My questions are: 1. How do I make sure PersonServiceXW has been initialized already by the XWiki CM before binding it for Guice ?
List GuiceServletContextListener AFTER XWikiServletContextListener in web.xml. The servlet spec specifies that listeners are called in the order they are encountered in web.xml, and XWikiServletContextListener is the one that starts our component manager.
For the future: we should not use other servlet context listener other than the xwiki one. We need it to init the CM but once this is done everything else should be done with it. So ideally you should instead create an EventListener that listen for the application start event and initizalize shindig in there rather than use an environment-specific servlet context listener. -Vincent
2. How do I get the initialized PersonServiceXW instance from XWSocialModule?
com.xpn.xwiki.web.Utils.getComponent(PersonServiceXW.class)
Vincent Massol wrote:
On Aug 10, 2009, at 12:41 PM, Sergiu Dumitriu wrote:
Anamaria Stoica wrote:
It looks like you can bind an instance to type in Guice. This is done either with Instance Bindings, @Provides Methods or Provider Bindings, depending on the complexity of the class. (http://code.google.com/p/google-guice/wiki/Bindings)
All bindings are defined in a class that extends AbstractModule, this would be XWSocialModule in my code ( https://svn.xwiki.org/svnroot/xwiki/sandbox/gsoc/opensocial/xwiki-social-ope...) .
These modules are then passed as arguments to Guice.createInjector(), which builds the injector. In my application, the injector is build by GuiceServletContextListener ( http://svn.apache.org/repos/asf/incubator/shindig/trunk/java/common/src/main...) This servlet takes the context parameters defined in my web.xml; these are:
<context-param> <param-name>guice-modules</param-name> <param-value> org.apache.shindig.common.PropertiesModule: org.apache.shindig.gadgets.DefaultGuiceModule: org.apache.shindig.gadgets.oauth.OAuthModule: org.apache.shindig.common.cache.ehcache.EhCacheModule: org.xwiki.opensocial.social.XWSocialModule </param-value> </context-param>
<listener>
<listener- class>org.xwiki.container.servlet.XWikiServletContextListener</ listener-class> </listener>
Now, all I need to do is bind the instance of PersonServiceXW after it has been initialized by XWiki's Component Manager. The binding will be done in XWSocialModule, using one of the instance binding methods (Instance Bindings, @Provides Methods or Provider Bindings).
My questions are: 1. How do I make sure PersonServiceXW has been initialized already by the XWiki CM before binding it for Guice ? List GuiceServletContextListener AFTER XWikiServletContextListener in web.xml. The servlet spec specifies that listeners are called in the order they are encountered in web.xml, and XWikiServletContextListener is the one that starts our component manager.
For the future: we should not use other servlet context listener other than the xwiki one. We need it to init the CM but once this is done everything else should be done with it.
So ideally you should instead create an EventListener that listen for the application start event and initizalize shindig in there rather than use an environment-specific servlet context listener.
I'm not sure, but I think that Shindig works this way, there's nothing we can do about it.
-Vincent
2. How do I get the initialized PersonServiceXW instance from XWSocialModule? com.xpn.xwiki.web.Utils.getComponent(PersonServiceXW.class)
-- Sergiu Dumitriu http://purl.org/net/sergiu/
On Aug 10, 2009, at 1:31 PM, Sergiu Dumitriu wrote:
Vincent Massol wrote:
On Aug 10, 2009, at 12:41 PM, Sergiu Dumitriu wrote:
Anamaria Stoica wrote:
It looks like you can bind an instance to type in Guice. This is done either with Instance Bindings, @Provides Methods or Provider Bindings, depending on the complexity of the class. (http://code.google.com/p/google-guice/wiki/Bindings)
All bindings are defined in a class that extends AbstractModule, this would be XWSocialModule in my code ( https://svn.xwiki.org/svnroot/xwiki/sandbox/gsoc/opensocial/xwiki-social-ope...) .
These modules are then passed as arguments to Guice.createInjector(), which builds the injector. In my application, the injector is build by GuiceServletContextListener ( http://svn.apache.org/repos/asf/incubator/shindig/trunk/java/common/src/main...) This servlet takes the context parameters defined in my web.xml; these are:
<context-param> <param-name>guice-modules</param-name> <param-value> org.apache.shindig.common.PropertiesModule: org.apache.shindig.gadgets.DefaultGuiceModule: org.apache.shindig.gadgets.oauth.OAuthModule: org.apache.shindig.common.cache.ehcache.EhCacheModule: org.xwiki.opensocial.social.XWSocialModule </param-value> </context-param>
<listener>
<listener- class>org.xwiki.container.servlet.XWikiServletContextListener</ listener-class> </listener>
Now, all I need to do is bind the instance of PersonServiceXW after it has been initialized by XWiki's Component Manager. The binding will be done in XWSocialModule, using one of the instance binding methods (Instance Bindings, @Provides Methods or Provider Bindings).
My questions are: 1. How do I make sure PersonServiceXW has been initialized already by the XWiki CM before binding it for Guice ? List GuiceServletContextListener AFTER XWikiServletContextListener in web.xml. The servlet spec specifies that listeners are called in the order they are encountered in web.xml, and XWikiServletContextListener is the one that starts our component manager.
For the future: we should not use other servlet context listener other than the xwiki one. We need it to init the CM but once this is done everything else should be done with it.
So ideally you should instead create an EventListener that listen for the application start event and initizalize shindig in there rather than use an environment-specific servlet context listener.
I'm not sure, but I think that Shindig works this way, there's nothing we can do about it.
Just checked http://svn.apache.org/repos/asf/incubator/shindig/trunk/java/common/src/main... It doesn't do much, just init Guice in a few lines. Thanks -Vincent
-Vincent
2. How do I get the initialized PersonServiceXW instance from XWSocialModule? com.xpn.xwiki.web.Utils.getComponent(PersonServiceXW.class)
On Mon, Aug 10, 2009 at 2:51 PM, Vincent Massol <[email protected]> wrote:
On Aug 10, 2009, at 1:31 PM, Sergiu Dumitriu wrote:
Vincent Massol wrote:
On Aug 10, 2009, at 12:41 PM, Sergiu Dumitriu wrote:
Anamaria Stoica wrote:
It looks like you can bind an instance to type in Guice. This is done either with Instance Bindings, @Provides Methods or Provider Bindings, depending on the complexity of the class. (http://code.google.com/p/google-guice/wiki/Bindings)
All bindings are defined in a class that extends AbstractModule, this would be XWSocialModule in my code (
https://svn.xwiki.org/svnroot/xwiki/sandbox/gsoc/opensocial/xwiki-social-ope... )
.
These modules are then passed as arguments to Guice.createInjector(), which builds the injector. In my application, the injector is build by GuiceServletContextListener (
http://svn.apache.org/repos/asf/incubator/shindig/trunk/java/common/src/main... )
This servlet takes the context parameters defined in my web.xml; these are:
<context-param> <param-name>guice-modules</param-name> <param-value> org.apache.shindig.common.PropertiesModule: org.apache.shindig.gadgets.DefaultGuiceModule: org.apache.shindig.gadgets.oauth.OAuthModule: org.apache.shindig.common.cache.ehcache.EhCacheModule: org.xwiki.opensocial.social.XWSocialModule </param-value> </context-param>
<listener>
<listener- class>org.xwiki.container.servlet.XWikiServletContextListener</ listener-class> </listener>
Now, all I need to do is bind the instance of PersonServiceXW after it has been initialized by XWiki's Component Manager. The binding will be done in XWSocialModule, using one of the instance binding methods (Instance Bindings, @Provides Methods or Provider Bindings).
My questions are: 1. How do I make sure PersonServiceXW has been initialized already by the XWiki CM before binding it for Guice ? List GuiceServletContextListener AFTER XWikiServletContextListener in web.xml. The servlet spec specifies that listeners are called in the order they are encountered in web.xml, and XWikiServletContextListener is the one that starts our component manager.
For the future: we should not use other servlet context listener other than the xwiki one. We need it to init the CM but once this is done everything else should be done with it.
So ideally you should instead create an EventListener that listen for the application start event and initizalize shindig in there rather than use an environment-specific servlet context listener.
I'm not sure, but I think that Shindig works this way, there's nothing we can do about it.
Just checked
http://svn.apache.org/repos/asf/incubator/shindig/trunk/java/common/src/main...
It doesn't do much, just init Guice in a few lines.
The important part is creating the injector: Injector injector = Guice.createInjector(Stage.PRODUCTION, modules); I don't know how setting/registering the context part works though.
Thanks -Vincent
-Vincent
2. How do I get the initialized PersonServiceXW instance from XWSocialModule? com.xpn.xwiki.web.Utils.getComponent(PersonServiceXW.class)
devs mailing list [email protected] http://lists.xwiki.org/mailman/listinfo/devs
Hi, I extended one of the servlets (JsonRpcServlet [0]) handling the Shindig calls (/social/rpc/*) just for testing. The new servlet is called XWikiShindigServlet (see complete class code at the bottom). XWikiShindigServlet initializes the XWiki Context and container components similar to XWiki GWT and REST services. (see class code at bottom) Should this be enough or the resulted context has to be passed further along from call to call until reaches PersonServiceXW [1] ? And, in PersonServiceXW can I still use @Requirement DocumentAccessBridge to access the component, or do I have to use the XWiki context like in XWikiServiceImpl [2], with calls like, for example: XWikiDocument doc = context.getWiki().getDocument(fullName, context); Note: there are about other 7 servlets in Shindig, some of them use a GadgetContext [3] object as context. I didn't look closely to all of them how they work. The approximate inverted call stack I'm looking at looks like this: org.xwiki.opensocial.social.XWikiShindigServlet.doPost(HttpServletRequest, HttpServletResponse) org.apache.shindig.protocol.JsonRpcServlet.doPost(HttpServletRequest, HttpServletResponse) org.apache.shindig.protocol.JsonRpcServlet.dispatchBatch(JSONArray, Map<String, FormDataItem>, HttpServletRequest, HttpServletResponse, SecurityToken) org.apache.shindig.protocol.JsonRpcServlet.getHandler(JSONObject, HttpServletRequest) org.apache.shindig.protocol.DefaultHandlerRegistry.getRpcHandler(JSONObject) org.apache.shindig.protocol.DefaultHandlerRegistry.RpcInvocationWrapper.execute(Map<String, FormDataItem>, SecurityToken, BeanConverter) org.apache.shindig.protocol.DefaultHandlerRegistry.RpcInvocationHandler.execute(JSONObject, Map<String, FormDataItem>, SecurityToken, BeanConverter) org.apache.shindig.social.opensocial.service.PersonHandler.get(SocialRequestItem) org.xwiki.opensocial.social.spi.internal.PersonServiceXW.getPerson(UserId, Set<String>, SecurityToken) [0] - https://svn.apache.org/repos/asf/incubator/shindig/trunk/java/common/src/mai... [1] - https://svn.xwiki.org/svnroot/xwiki/sandbox/gsoc/opensocial/xwiki-social-ope... [2] - http://svn.xwiki.org/svnroot/xwiki/platform/web/trunk/gwt/src/main/java/com/... [3] - http://svn.apache.org/repos/asf/incubator/shindig/trunk/java/gadgets/src/mai... public class XWikiShindigServlet extends JsonRpcServlet { private XWikiContext context; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { try { this.context = initializeXWikiContext(req, resp); super.doGet(req, resp); } finally { if (context != null) { cleanupContainerComponents(); } } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { try { this.context = initializeXWikiContext(req, resp); super.doPost(req, resp); } finally { if (context != null) { cleanupContainerComponents(); } } } private XWikiContext initializeXWikiContext(HttpServletRequest req, HttpServletResponse resp) throws XWikiException, ServletException { XWikiEngineContext engine = new XWikiServletContext(getServletContext()); XWikiRequest request = new XWikiServletRequest(req); XWikiResponse response = new XWikiServletResponse(resp); XWikiContext context = Utils.prepareContext("", request, response, engine); // Initialize the Container component which is the new way of transporting the Context in the new // component architecture. initializeContainerComponent(context); return context; } private void initializeContainerComponent(XWikiContext context) throws ServletException { // Initialize the Container fields (request, response, session). // Note that this is a bridge between the old core and the component architecture. // In the new component architecture we use ThreadLocal to transport the request, // response and session to components which require them. ServletContainerInitializer containerInitializer = (ServletContainerInitializer) Utils.getComponent(ServletContainerInitializer.class); try { containerInitializer.initializeRequest(context.getRequest().getHttpServletRequest(), context); containerInitializer.initializeResponse(context.getResponse().getHttpServletResponse()); containerInitializer.initializeSession(context.getRequest().getHttpServletRequest()); } catch (ServletContainerException e) { throw new ServletException("Failed to initialize request/response or session", e); } } private void cleanupContainerComponents() { Container container = (Container) Utils.getComponent(Container.class); Execution execution = (Execution) Utils.getComponent(Execution.class); // We must ensure we clean the ThreadLocal variables located in the Container and Execution // components as otherwise we will have a potential memory leak. container.removeRequest(); container.removeResponse(); container.removeSession(); execution.removeContext(); } } Thanks, Anamaria On Mon, Aug 10, 2009 at 4:28 PM, Anamaria Stoica <[email protected]>wrote:
On Mon, Aug 10, 2009 at 2:51 PM, Vincent Massol <[email protected]>wrote:
On Aug 10, 2009, at 1:31 PM, Sergiu Dumitriu wrote:
Vincent Massol wrote:
On Aug 10, 2009, at 12:41 PM, Sergiu Dumitriu wrote:
Anamaria Stoica wrote:
It looks like you can bind an instance to type in Guice. This is done either with Instance Bindings, @Provides Methods or Provider Bindings, depending on the complexity of the class. (http://code.google.com/p/google-guice/wiki/Bindings)
All bindings are defined in a class that extends AbstractModule, this would be XWSocialModule in my code (
https://svn.xwiki.org/svnroot/xwiki/sandbox/gsoc/opensocial/xwiki-social-ope... )
.
These modules are then passed as arguments to Guice.createInjector(), which builds the injector. In my application, the injector is build by GuiceServletContextListener (
http://svn.apache.org/repos/asf/incubator/shindig/trunk/java/common/src/main... )
This servlet takes the context parameters defined in my web.xml; these are:
<context-param> <param-name>guice-modules</param-name> <param-value> org.apache.shindig.common.PropertiesModule: org.apache.shindig.gadgets.DefaultGuiceModule: org.apache.shindig.gadgets.oauth.OAuthModule: org.apache.shindig.common.cache.ehcache.EhCacheModule: org.xwiki.opensocial.social.XWSocialModule </param-value> </context-param>
<listener>
<listener- class>org.xwiki.container.servlet.XWikiServletContextListener</ listener-class> </listener>
Now, all I need to do is bind the instance of PersonServiceXW after it has been initialized by XWiki's Component Manager. The binding will be done in XWSocialModule, using one of the instance binding methods (Instance Bindings, @Provides Methods or Provider Bindings).
My questions are: 1. How do I make sure PersonServiceXW has been initialized already by the XWiki CM before binding it for Guice ? List GuiceServletContextListener AFTER XWikiServletContextListener in web.xml. The servlet spec specifies that listeners are called in the order they are encountered in web.xml, and XWikiServletContextListener is the one that starts our component manager.
For the future: we should not use other servlet context listener other than the xwiki one. We need it to init the CM but once this is done everything else should be done with it.
So ideally you should instead create an EventListener that listen for the application start event and initizalize shindig in there rather than use an environment-specific servlet context listener.
I'm not sure, but I think that Shindig works this way, there's nothing we can do about it.
Just checked
http://svn.apache.org/repos/asf/incubator/shindig/trunk/java/common/src/main...
It doesn't do much, just init Guice in a few lines.
The important part is creating the injector:
Injector injector = Guice.createInjector(Stage.PRODUCTION, modules);
I don't know how setting/registering the context part works though.
Thanks -Vincent
-Vincent
2. How do I get the initialized PersonServiceXW instance from XWSocialModule? com.xpn.xwiki.web.Utils.getComponent(PersonServiceXW.class)
devs mailing list [email protected] http://lists.xwiki.org/mailman/listinfo/devs
On Mon, Aug 10, 2009 at 1:41 PM, Sergiu Dumitriu <[email protected]> wrote:
Anamaria Stoica wrote:
It looks like you can bind an instance to type in Guice. This is done either with Instance Bindings, @Provides Methods or Provider Bindings, depending on the complexity of the class. (http://code.google.com/p/google-guice/wiki/Bindings)
All bindings are defined in a class that extends AbstractModule, this would be XWSocialModule in my code (
https://svn.xwiki.org/svnroot/xwiki/sandbox/gsoc/opensocial/xwiki-social-ope... ).
These modules are then passed as arguments to Guice.createInjector(),
which
builds the injector. In my application, the injector is build by GuiceServletContextListener (
http://svn.apache.org/repos/asf/incubator/shindig/trunk/java/common/src/main... )
This servlet takes the context parameters defined in my web.xml; these are:
<context-param> <param-name>guice-modules</param-name> <param-value> org.apache.shindig.common.PropertiesModule: org.apache.shindig.gadgets.DefaultGuiceModule: org.apache.shindig.gadgets.oauth.OAuthModule: org.apache.shindig.common.cache.ehcache.EhCacheModule: org.xwiki.opensocial.social.XWSocialModule </param-value> </context-param>
<listener>
<listener-class>org.xwiki.container.servlet.XWikiServletContextListener</listener-class>
</listener>
Now, all I need to do is bind the instance of PersonServiceXW after it has been initialized by XWiki's Component Manager. The binding will be done in XWSocialModule, using one of the instance binding methods (Instance Bindings, @Provides Methods or Provider Bindings).
My questions are: 1. How do I make sure PersonServiceXW has been initialized already by the XWiki CM before binding it for Guice ?
List GuiceServletContextListener AFTER XWikiServletContextListener in web.xml. The servlet spec specifies that listeners are called in the order they are encountered in web.xml, and XWikiServletContextListener is the one that starts our component manager.
I already had listed the Guice listener after the XWiki one in my web.xml. <!-- Initializes XWiki --> <listener> <listener-class>org.xwiki.container.servlet.XWikiServletContextListener</listener-class> </listener> <!-- Shindig Guice listener --> <listener> <listener-class>org.apache.shindig.common.servlet.GuiceServletContextListener</listener-class> </listener>
2. How do I get the initialized PersonServiceXW instance from XWSocialModule?
com.xpn.xwiki.web.Utils.getComponent(PersonServiceXW.class)
Here I modified XWSocialModule to look like this: //bind(PersonService.class).to(PersonServiceXW.class); PersonServiceXW psxw = (PersonServiceXW) Utils.getComponent(SocialServiceComponent.class, "PersonServiceXW"); bind(PersonService.class).toInstance(psxw); The PersonServiceXW code is: public Future<Person> getPerson(UserId userId, Set<String> fields, SecurityToken token) throws ProtocolException { Person person = new PersonXW(); person.setId("XWiki.Julia"); if (!documentAccessBridge.exists("XWiki.Julia")) //some code } //some other code } The outcome: I get a NPE when trying to get the context from DefaultExtension, exactly like the one send earlier in a previous mail (stacktrace here http://ana-s-private-labs.pastebin.com/m655cdf70) What could be going wrong here ? Thanks, Anamaria
-- Sergiu Dumitriu http://purl.org/net/sergiu/ _______________________________________________ devs mailing list [email protected] http://lists.xwiki.org/mailman/listinfo/devs
participants (3)
-
Anamaria Stoica -
Sergiu Dumitriu -
Vincent Massol