hi Simon - Great! That worked. I am now getting back results! Thank you. No null-pointers. -------------------- So I wanted to clarify your solution for the permanent approach.
If I use a Unique ID for each request: 1. How should I generate this ID? 2. I thought composite references were injected in as per Singleton pattern - a new object for each thread. 3. In going the UniqueID / HashMap way would I not be programming to the framework - rather than a POJO model. 4. Is there another approach to this issue? I need to read up on the various Scopes. 5. Does this scale effectively for QueryResults on multiple nodes with each having a large set of some collections? of course I would be removing the entry from the HashMap so maybe its not an issue. -------------------- Just trying to understand the right approach to the framework. And thanks again! monosij On Thu, Apr 21, 2011 at 2:59 PM, Simon Nash <[email protected]> wrote: > Monosij Dutta-Roy wrote: > >> hi Simon - >> >> Made the changes as suggested and <reference> is now only in >> QueryExecutor. All others pure Java. Thanks for the help and suggestions. >> I tried just getting the size of the ArrayList in QueryExecutor and I lose >> it right after I set it in the ServiceReference object on QueryExecutor. >> -------------------- >> So in QueryExecutor I try as below where QueryResults declared as a >> ServiceReference: >> >> @Reference >> protected ServiceReference<QueryResults> queryResults; >> >> 1. System.out.println("Patients Count (Before ServiceReference): " + >> alPatients.size()); >> 2. queryResults.getService().setResults(alPatients); >> 3. System.out.println("Patients Count (In ServiceReference): " + >> queryResults.getService().getResults().size()); >> >> 1 Returns the correct size of ArrayList of Patients in getting from >> database. >> 2. Sets the ArrayList in the QueryResults object declared as a >> ServiceReference injection for QueryExecutor. >> 3. Try to get the size of the ArrayList in the ServiceReference object >> QueryResults and get the null-pointer error. >> >> Did not have to try it from QueryServlet. It does not seem to set it in >> the ServiceReference object. Running JDK 1.6.0.20. >> -------------------- >> Thanks again for all your help. >> >> Thanks for trying this. This narrows down the problem and I think > I know what is happening. > > I think the problem is the scope of the QueryResults service > implementation. > If it has the default scope (STATELESS), a new instance of the > implementation > class will be created for every service invocation. So when you invoke > getResults() you are getting a different instance than when you invoked > setResults(). This would happen whether or not you use a ServiceReference > to invoke setResults() and getResults(). > > A quick fix to solve this problem is to set @Scope("COMPOSITE") on the > QueryResults implementation class. This will create a single instance > object for the QueryResults service and use it for all calls to this > service. > If you only have one client, this will work fine. However, if you have > more > than one client, this won't work because of the following scenario: > client 1 -> setResults(results) > client 2 -> setResults(results) > client 1 -> getResults() > client 2 -> getResults() > This will cause client 1 to get the results set by client 2, which isn't > correct. > > The solution to this problem is to use @Scope("COMPOSITE") for the > QueryResults implementation class and give each client a unique ID which > is passed by the client to the QueryResults service. The sequence of > calls above would change to the following: > client 1 -> setResults(client1ID, results) > client 2 -> setResults(client2ID, results) > client 1 -> getResults(client1ID) > client 2 -> getResults(client2ID) > > The QueryResults implementation needs to keep a HashMap (or similar) that > holds multiple result sets and maps the unique client ID to the results > for that client. > > Simon > > monosij >> >> >> On Thu, Apr 21, 2011 at 4:36 AM, Simon Nash <[email protected] <mailto: >> [email protected]>> wrote: >> >> Hi Monosij, >> See comments below. >> >> Simon >> >> >> Monosij Dutta-Roy wrote: >> >> Simon - >> Thanks for your help with the ServiceReference - it is almost >> there but am getting a null-pointer error on trying to access >> the QueryResults. >> I have attached the error file generated. >> --------------------- >> Starting with QueryExecutor where I create the ServiceReference >> object as: @Reference >> protected ServiceReference<QueryResults> queryResults; >> >> That looks right. >> >> >> I pass it back through QueryOrchestrator > QueryService > >> QueryServlet and I declare the reference in *_each_* object the >> same as above. >> >> > >> You should only use the @Reference annotation in QueryExecutor. In the >> other classes you should declare it as a normal Java variable with the >> type ServiceReference<QueryResults>. >> >> >> And refer to it in the composite file as: >> >> <reference name="queryResults" >> target="QueryResultsComponent/QueryResults"> >> <interface.java interface="org.rd.qm.QueryResults"/> >> </reference> >> >> You should only be doing this in QueryExecutor. >> >> >> It seems to work as now I do not get the PassByValue error >> anymore. --------------------- >> But now I get a null-pointer error when trying to access the >> QueryResults object in the ServiceReference object. >> I set the ServiceReference<QueryResults> queryResults in >> QueryExecutor as: >> >> first this way: >> queryResults.getService().setResults(alPatients); >> >> That looks right. >> >> >> second in this way: >> QueryResults quRes = new QueryResultsImpl(); >> quRes.setResults(alPatients); >> queryResults.getBusinessInterface().cast(quRes); >> >> That doesn't look right. >> >> >> Essentially I am trying to set the ArrayList of results in >> QueryResults and in QueryServlet trying to display the ArrayList. >> >> So in QueryServlet I try to access the ArrayList as: >> ArrayList alPatients = queryResults.getService().getResults(); >> >> That looks right. >> >> >> This seems to be fine as I get an ArrayList >> But I get a null-pointer when I try to iterate the ArrayList. >> >> > >> I'm not sure why this is happening. You should get the same contents >> from doing this in QueryServlet as you would get if you did it in >> QueryExecutor after the setResults() call. Can you try interating the >> ArrayList in QueryExecutor after calling setResults() to see if that >> works OK? >> >> >> --------------------- >> Questions: >> >> 1. Seems the way I set I have set up the ServiceReference is >> working. Is that the best way to set up the ServiceReference? If >> so it seems like it would be a good idea to have >> ServiceReferences as a separate contribution that is 'passed >> around'. And then take it a step further by setting >> ServiceReferences as JAXB datatypes. >> >> Contributions aren't passed around at runtime. The way you are doing >> it >> (with the changes/corrections that I suggested above) is fine. I think >> it's best to defer the JAXB issues until you have got the non-JAXB code >> working. >> >> >> 2. I had to set up the ServiceReference in each obect, even in >> QueryServlet. QueryServlet which calls QueryService (in same >> composite) still needs to pass back QueryResults as a >> ServiceReference since QueryService is defined as Remotable. I >> was planning on using QueryService for housekeeping while still >> making it Remotable - and pass back to QueryServlet only what is >> needed (so servlet framework can be swapped out). But now it >> seems I have to make the QueryServlet (ie the Servlet framework) >> depend on QueryResult or such. Is there a way to avoid this? Am >> I thinking about this the right way? I am thinking QueryServlet >> should only know and depend on QueryService in the same >> composite. I guess then QueryService has to be Local? >> >> If you make QueryService local, this means the code for QueryService >> will always run in the same webapp as QueryServlet. Is that what >> you want? Originally I thought you wanted to keep the back-end logic >> separate from the UI framework. Is QueryService part of the back-end >> logic or is it part of the UI framework? >> >> >> 3. This is a question for later once I get this working but I am >> currently importing QueryOrchestrator in QueryService (webapp). >> Would there be a way to go around this and not have >> QueryOrchestrator connected at all. I am assuming I can go the >> ws.binding route and just call the webservice that >> QueryOrchestrator will service - but I lose the non-ws.binding >> connectivity. Would there be a way to just depend on >> QueryResults - that is shared by everyone and is a >> ServiceReference - to make it happen. I am just shooting in dark >> here a little. But my thought is I should only want to depend on >> QueryResults and not worry about how I get QueryResults. I guess >> I will need to try some approaches. >> >> I'm not sure what the purpose of QueryOrchestrator is. As you say, >> getting >> it working is the first priority. When you have it working, you can >> look >> at the end-to-end design and make changes incrementally to change the >> component structure as needed. With SCA, this should be easy to do. >> >> >> 4. This maybe related, not a big deal but strange. I am using >> Eclipse Helios on Ubuntu and since I started using >> ServiceReference - the objects from the third composite: >> domainBCA - which are Person and PhysicalLocation have an error >> marker on them as 'import not found'. I tried deleting them and >> recreating the imports, it still remains. Removing >> ServiceReference makes those go away. However it does not create >> a problem as such as Maven compiles fine - but it is happening >> in both the composites: controller and servlet. >> --------------------- >> Thanks for all your help and patience. >> >> My guess is that your Eclipse workspace is missing a dependency on the >> Tuscany library that provides the definition of the ServiceReference >> interface. >> >> Simon >> >> monosij >> >> >> >> ------------------------------------------------------------------------ >> >> >> HTTP ERROR 500 >> >> Problem accessing /qmAppSCA01/QueryServlet. Reason: >> >> INTERNAL_SERVER_ERROR >> >> >> Caused by: >> >> java.lang.NullPointerException >> at >> org.rd.qm.servlet.QueryServlet.getPatients(QueryServlet.java:74) >> at >> org.rd.qm.servlet.QueryServlet.service(QueryServlet.java:91) >> at >> javax.servlet.http.HttpServlet.service(HttpServlet.java:820) >> at >> >> org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511) >> at >> >> org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:401) >> at >> >> org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) >> at >> >> org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) >> at >> >> org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:766) >> at >> >> org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:450) >> at >> >> >> org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230) >> at >> >> >> org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114) >> at >> >> org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) >> at org.mortbay.jetty.Server.handle(Server.java:326) >> at >> >> org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) >> at >> >> >> org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:945) >> at >> org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:756) >> at >> org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218) >> at >> org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) >> at >> >> org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410) >> at >> >> >> org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582) >> >> >> ------------------------------------------------------------------------ >> /Powered by Jetty:/// >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >
