2017-03-09 3 views
0

サーバーの起動時に実行される遅延タスクを作成しました。ここでは、エンドポイントは、最終的にタスクを実行ContextListenerです:遅延タスク:しばらくしてnullになる参照。

public class ServerSetupListenerVer1 implements ServletContextListener { 


    @Override 
    public void contextInitialized(ServletContextEvent sce) { 
     //Endpoint service 
     final LearnerProfileVer2PersistenceEndpoint learnerEndpoint = new LearnerProfileVer2PersistenceEndpoint(); 
     final TutorProfileVer2PersistenceEndpoint tutorEndpoint = new TutorProfileVer2PersistenceEndpoint(); 

     //Retrieve the dummy profile data 
     final LearnerProfileVer1[] learnerProfiles = (LearnerProfileVer1[]) ProfileUtils.getJSONToProfiles(STATUS_LEARNER); 
     final TutorProfileVer1[] tutorProfiles = (TutorProfileVer1[]) ProfileUtils.getJSONToProfiles(STATUS_TUTOR); 

     //Insert this data into the datastore 
     ObjectifyService.run(new VoidWork() { 
      @Override 
      public void vrun() { 
       for(LearnerProfileVer1 profile : learnerProfiles){ 
        learnerEndpoint.insert(profile); 
       } 
       for(TutorProfileVer1 profile : tutorProfiles){ 
        tutorEndpoint.insert(profile); 
       } 
      } 
     }); 
    } 

    @Override 
    public void contextDestroyed(ServletContextEvent sce) { 

    } 
} 

あなたは、私がここへの参照を保管しております2つのエンドポイントがあることがわかります。これらの両方のエンドポイントには、実行するための共通の遅延タスクがあります。延期タスクを以下に示します。

基本的に
static class LocationTask implements DeferredTask { 

     private Account acc; 
     private LatLng geoCoordinates; 
     private int retries = 0; 

     public LocationTask(final Account acc, final LatLng geoCoordinates) { 
      logger.info("Profile at the time of task creation: " + acc.getProfile()); 
      this.acc = acc; 
      this.geoCoordinates = geoCoordinates; 
     } 

     @Override 
     public void run() { 
      logger.info("Profile at the time of DeferredTask.run() call " + acc.getProfile()); 
      String response = LocationUtil.getFormattedAddress(geoCoordinates); 

      if((response = checkResponseCode(response)) != null){ 
       // Stash the address into the Datastore 
       logger.info("Profile to be updated with location-info: " + acc.getProfile()); 
       acc.setLocationInfo(new Account.LocationInfo(response)); 
       ofy().save().entity(acc).now(); 
      } 
     } 
     private String checkResponseCode(String response){ 
      if(response == null){ 
       return null; 
      } 
      if(response.equals("ZERO_RESULTS")){ 
       return null; 
      } 
      else if(response.equals("OVER_QUERY_LIMIT")){ 
       // We can re-request without any GET params except the LatLng 
       if(retries ++ == 1){ 
        return null; 
       } 
       return checkResponseCode(LocationUtil.getFormattedAddress(geoCoordinates, null)); 
      } 
      else if(response.equals("REQUEST_DENIED")){ 
       return null; 
      } 
      else if(response.equals("INVALID_REQUEST")){ 
       return null; 
      } 
      else if(response.equals("UNKNOWN_ERROR")){ 
       return null; 
      } 
      else{ 
       return response; 
      } 

     } 
    } 

、これらのエンドポイントは客観化を使用してデータストアにアカウントを挿入しますが、単にアカウントを挿入する前に、私は延期タスクを使用して、{緯度、経度}のアドレスを計算することを望んでいました。問題は、Accountクラス内のプロファイルへの参照が、タスクの実行時に消えてしまうことです。私はログステートメントを通してこれを確認しました。遅延タスクのコンストラクタのlogステートメントは、プロファイルの内容を出力しますが、run()メソッドからログオンしたときには同じプロファイルがnullになります。

驚くべきことは、LatLng geoCoordinatesのparamが生きてプロファイル自体の内部から検索されたことです。私が直接参照していない(paramsを介して)フィールドだけが生きていません。私はこれがタスクのシリアル化と関係しているのかどうか疑問に思っていました...

タスクは、エンドポイント要求(一度に1500)が処理された後に実行を開始することにも注意してください。次のように

また、新しいタスクは、各アカウントの作成のために作成されます。

void scheduleLocationInfoUpdation(final Account acc, final LatLng geoCoordinates){ 
     if(geoCoordinates == null){ 
      return; 
     } 
     //Using a deferred task 
     Queue queue = QueueFactory.getDefaultQueue(); 
     queue.addAsync(TaskOptions.Builder.withPayload(new LocationTask(acc, geoCoordinates))); 
    } 

これは本当に奇妙なシナリオです。誰が何が間違っているのか分かりますか?

答えて

0

はい、シリアル化されているためです。私はすべてのモデルクラスをSerializableに実装しましたが、参照は生きています。

関連する問題