Agreed. Best practices would be of great help. I guess your solution of a 'singleton' AdwordsServices would work. Is the following what you had in mind:
- The only time we need AdwordsServices is to create the service objects. The service objects can be created at any time during the long lived process. - We create only one global copy of the AdwordsServices object. - The first time access to an account is needed, we use the global AdwordsServices (in a thread safe way) to create all the service objects we will need for the whole duration of the process. - We cache the service objects instead of AdwordsServices at the account level, and hence no need to use AdwordsServices again. Oliver On Wednesday, October 10, 2012 5:00:38 PM UTC+1, j.e.frank wrote: > > My read was the same as yours: AdWordsServices doesn't retain the session. > We have thousands of accounts so I don't want to have one per account if > it's a "heavyweight" object as indicated in the migration guide. So that's > why I came up with idea of a wrapper object that will ensure thread safety. > > But I think this back-and-forth you and I are having is indicative of the > need for some additional examples or documentation of best practices, so > that each person doesn't have to puzzle it out and invent a solution. > > On Wednesday, October 10, 2012 7:30:13 AM UTC-4, Oliver wrote: >> >> I need to correct myself. AdwordsServices itself does not hold a >> reference to the session. It's the actual service objects generated from >> AdwordsServices that do. e.g. >> >> CampaignServiceInterface campaignService = adWordsServices.get(session, >> CampaignServiceInterface.class); >> >> >> But AdwordsServices is not thread safe, so caching it at the account >> level instead of the appliaction (multiple accounts) level will make things >> easier. >> >> Oliver >> >> >> On Wednesday, October 10, 2012 11:35:54 AM UTC+1, Oliver wrote: >>> >>> Here is what I think: >>> >>> The AdwordsServices object holds a reference to the AdwordsSession >>> object. Since AdwordsSession is linked to one account ID only, you need to >>> be very careful not to use AdwordsServices across accounts without >>> switching the session. >>> >>> What we do is create and cache a copy of AdwordsServices and >>> AdwordsSession for each account. The objects are re-used for all calls on >>> an account. We're careful not to use multithreads when accessing the >>> Service API for an account (AdwordsServices). Using multi-threads when >>> downloading reports is fine. >>> >>> Refreshtoken: my understanding is that the client libraries will take >>> care of automatically refreshing the OAuth2 token if needed (however, I >>> have not tested this yet). So, in theory, all you need to do is persist >>> the refresh token and keep using it until the end user revokes access. >>> >>> If anyone has better ideas than the above please let us know. >>> >>> Oliver >>> >>> >>> >>> Tuesday, October 9, 2012 7:28:45 PM UTC+1, j.e.frank wrote: >>>> >>>> I had seen that post, which is what prompted me to post my own. I am >>>> trying to better understand how multiple threads should/can share objects. >>>> I don't want to go the route of "each call creates its own set of >>>> objects", if there's a more efficient way to do things. >>>> >>>> As an example, consider the AdWordsServices class, which is new (to >>>> me). The migration guide says "The AdWordsServices object is fairly >>>> heavyweight and should be instantiated once and reused as much as >>>> possible." It is not thread-safe, but it doesn't retain any state. My >>>> conclusion is that if I make a singleton AdWordsServices object for use >>>> throughout my code, as long as I make sure no two threads are calling >>>> adWordsServices.get at the same time, that should be more efficient than >>>> creating a new one every time I need to make an AdWords API call. In >>>> order >>>> to achieve thread safety, I will probably wrap the AdWordsServices object >>>> inside my own singleton object, with a synchronized "get" method that >>>> passes through to the wrapped AdWordsServices object. That's an example >>>> of >>>> a best practice that I'm looking for. >>>> >>>> As for the OAuth2 credential, I have managed to create a valid one from >>>> a saved refresh token, by building the credential and then calling >>>> credential.refreshToken(). I'm still trying to figure out whether I need >>>> to do this refresh step or if it would happen automatically, and also >>>> whether calling refreshToken() is going to invalidate any >>>> AdWordsSession(s) >>>> that are currently using the credential before it got refreshed. I'm >>>> going >>>> to write some tests, and once I understand the credentials, tokens, and >>>> AdWordsSessions better, I will be able to come up with a coding strategy >>>> that fits my use case (long-lived services, all with the "same" login). >>>> But if there are examples already that match my use case, it will be a >>>> big >>>> time-saver and also make it more likely that I don't misunderstand how >>>> things work, or come up with a flawed solution. >>>> >>>> On Tuesday, October 9, 2012 1:42:49 PM UTC-4, Oliver wrote: >>>>> >>>>> You will need to persist the refresh token and account ID so your >>>>> services can resume on their own in case of a restart. You can ceate >>>>> valid >>>>> AdwordsSession and AdwordsServices on the fly if you have these two >>>>> fields. >>>>> >>>>> Also, this might be of help: >>>>> >>>>> https://groups.google.com/forum/?fromgroups=#!topic/adwords-api/zf0slvrjkMs >>>>> >>>>> Oliver >>>>> >>>>> On Tuesday, October 9, 2012 5:08:03 PM UTC+1, j.e.frank wrote: >>>>>> >>>>>> I am trying to migrate to v201209 from v201109. I have several >>>>>> long-lived services that use the AdWords API on behalf of my MCC >>>>>> account, >>>>>> for example to run reports, to get ad details, and so forth. I'm trying >>>>>> to >>>>>> understand how I should be using the new session/service objects, such >>>>>> that >>>>>> more than one thing can be happening at once, but that I don't create a >>>>>> new >>>>>> session or service object when I don't need to, and also that I use my >>>>>> OAuth2 tokens appropriately (refresh if necessary but not every time I >>>>>> need >>>>>> to make a call). I've seen several pieces of example code, but they are >>>>>> self-contained so they always get a new session, new service object, >>>>>> refresh the OAuth token, etc. Are there any examples more suitable for >>>>>> long-running services that will be invoked from time to time? >>>>> >>>>> -- =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ Also find us on our blog and discussion group: http://adwordsapi.blogspot.com http://groups.google.com/group/adwords-api =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ You received this message because you are subscribed to the Google Groups "AdWords API Forum" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/adwords-api?hl=en
