2012-08-27 7 views
5

Używam tego przykładu Google Toolkit/GSON, który pobiera dane ze Twittera.Total Noob to gwt/gson in eclipse, error: "Nie można wywołać konstruktora no-args dla klasy"

Wszystko kompiluje dobrze, ale kiedy debug jak Web Application, wszystko ładunku dobrze, ale po kliknięciu na przycisk „Szukaj” pojawia się następujący błąd:

SEVERE: javax.servlet.ServletContext log: Exception while dispatching incoming RPC call com.google.gwt.user.server.rpc.UnexpectedException: Service method 'public abstract java.util.List com.google.gwt.twittersearch.client.TwitterService.searchTweets(java.lang.String) throws java.io.IOException,java.lang.IllegalArgumentException' threw an unexpected exception: java.lang.RuntimeException: Unable to invoke no-args constructor for class com.google.gwt.twittersearch.server.TwitterServiceImpl$SearchResponse. Register an InstanceCreator with Gson for this type may fix this problem. at com.google.gwt.user.server.rpc.RPC.encodeResponseForFailure(RPC.java:385) at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:588) at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:208) at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:248) at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:62) at javax.servlet.http.HttpServlet.service(HttpServlet.java:637) at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166) at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:35) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:60) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.tools.development.BackendServersFilter.doFilter(BackendServersFilter.java:97) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) 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:765) at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:94) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:370) 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:938) at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755) 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:409) at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582) Caused by: java.lang.RuntimeException: Unable to invoke no-args constructor for class com.google.gwt.twittersearch.server.TwitterServiceImpl$SearchResponse. Register an InstanceCreator with Gson for this type may fix this problem. at com.google.gson.internal.ConstructorConstructor$8.construct(ConstructorConstructor.java:167) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:162) at com.google.gson.Gson.fromJson(Gson.java:795) at com.google.gson.Gson.fromJson(Gson.java:734) at com.google.gwt.twittersearch.server.TwitterServiceImpl.parseSearchResponse(TwitterServiceImpl.java:80) at com.google.gwt.twittersearch.server.TwitterServiceImpl.searchTweets(TwitterServiceImpl.java:35) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at com.google.appengine.tools.development.agent.runtime.Runtime.invoke(Runtime.java:115) at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:569) ... 34 more Caused by: java.lang.UnsupportedOperationException: Cannot allocate class com.google.gwt.twittersearch.server.TwitterServiceImpl$SearchResponse at com.google.gson.internal.UnsafeAllocator$4.newInstance(UnsafeAllocator.java:100) at com.google.gson.internal.ConstructorConstructor$8.construct(ConstructorConstructor.java:164) ... 45 more

Oto kod TwitterServiceImpl :

package com.google.gwt.twittersearch.server; 

import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.Reader; 
import java.net.HttpURLConnection; 
import java.net.URL; 
import java.net.URLEncoder; 
import java.util.List; 

import com.google.gwt.twittersearch.client.Tweet; 
import com.google.gwt.twittersearch.client.TwitterService; 
import com.google.gson.Gson; 
import com.google.gwt.user.server.rpc.RemoteServiceServlet; 

@SuppressWarnings("serial") 
public class TwitterServiceImpl extends RemoteServiceServlet implements 
     TwitterService { 

    @Override 
    public List<Tweet> searchTweets(String query) throws IllegalArgumentException, IOException { 
      query = query.trim(); 
      if (query.isEmpty()) { 
      throw new IllegalArgumentException("No search query specified."); 
      } 

      // see: https://dev.twitter.com/docs/api/1/get/search 
      String q = URLEncoder.encode(query, "UTF-8"); 
      URL url = new URL("http://search.twitter.com/search.json?q=" + q); 
      HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 
      InputStream response = null; 
      try { 
      response = connection.getInputStream(); 
      return parseSearchResponse(response); 
      } finally { 
      if (response != null) { 
       response.close(); 
      } 
      } 
    } 

    @Override 
    public String getPrivacyPolicy() throws IOException { 
     // see: https://dev.twitter.com/docs/api/1/get/legal/privacy 
     URL url = new URL("https://api.twitter.com/1/legal/privacy.json"); 
     HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 
     InputStream response = null; 
     try { 
      response = connection.getInputStream(); 
      return parsePolicyResponse(response); 
     } finally { 
      if (response != null) { 
       response.close(); 
      } 
     } 
    } 

    /** 
    * Parses the privacy policy response returned from the Twitter API. 
    * @param response the response 
    * @return the privacy policy 
    * @throws IOException if there was a problem reading the response 
    */ 
    private String parsePolicyResponse(InputStream response) throws IOException { 
     Reader reader = new InputStreamReader(response); 
     PrivacyPolicyResponse privacyPolicyResponse = new Gson().fromJson(reader, PrivacyPolicyResponse.class); 
     return privacyPolicyResponse.privacy; 
    } 

    /** 
    * Parses the search response returned from the Twitter API. 
    * @param response the response 
    * @return the search results 
    * @throws IOException if there was a problem reading the response 
    */ 

    private List<Tweet> parseSearchResponse(InputStream response) throws IOException { 
      Reader reader = new InputStreamReader(response); 
      SearchResponse searchResponse = new Gson().fromJson(reader, SearchResponse.class); 
      return searchResponse.results; 
     } 

    private class PrivacyPolicyResponse { 
    public String privacy; 
    } 


    private class SearchResponse { 
     public List<Tweet> results; 
    } 

} 

Oto kod punktu wejścia:

package com.google.gwt.twittersearch.client; 

import java.util.List; 
import com.google.gwt.safehtml.shared.SafeHtmlBuilder; 
import com.google.gwt.core.client.EntryPoint; 
import com.google.gwt.core.client.GWT; 
import com.google.gwt.event.dom.client.ClickEvent; 
import com.google.gwt.event.dom.client.ClickHandler; 
import com.google.gwt.user.client.rpc.AsyncCallback; 
import com.google.gwt.user.client.ui.Button; 
import com.google.gwt.user.client.ui.HTML; 
import com.google.gwt.user.client.ui.HorizontalPanel; 
import com.google.gwt.user.client.ui.Image; 
import com.google.gwt.user.client.ui.Label; 
import com.google.gwt.user.client.ui.Panel; 
import com.google.gwt.user.client.ui.RootPanel; 
import com.google.gwt.user.client.ui.TextBox; 
import com.google.gwt.user.client.ui.VerticalPanel; 

/** 
* Entry point classes define <code>onModuleLoad()</code>. 
*/ 
public class TwitterSearch implements EntryPoint { 
    private Button privacyPolicyButton; 
    private Button searchButton; 
    private TextBox searchQueryTextBox; 
    private Panel resultsPanel; 
    private Label errorLabel; 
    private Image loadingImage; 
    private final TwitterServiceAsync service = GWT.create(TwitterService.class); 

/** 
* This is the entry point method. 
*/ 
public void onModuleLoad() { 
    createWidgets(); 
    layoutWidgets(); 

} 

private void createWidgets() { 
    searchQueryTextBox = new TextBox(); 

    searchButton = new Button("Search"); 
    searchButton.addClickHandler(new ClickHandler() { 
     @Override 
     public void onClick(ClickEvent event) { 
      setLoading(true); 
      String query = searchQueryTextBox.getText(); 
      service.searchTweets(query, new AsyncCallback<List<Tweet>>() { 
       @Override 
       public void onFailure(Throwable caught) { 
        errorLabel.setText(caught.getMessage()); 
        errorLabel.setVisible(true); 
        setLoading(false); 
       } 

       @Override 
       public void onSuccess(List<Tweet> result) { 
        resultsPanel.clear(); 
        for (Tweet tweet : result) { 
         SafeHtmlBuilder builder = new SafeHtmlBuilder(); 
         builder.appendHtmlConstant("<b>User: </b>"); 
         builder.appendEscaped(tweet.getFrom_user()); 
         builder.appendHtmlConstant("<br /><b>Created: </b>"); 
         builder.appendEscaped(tweet.getCreated_at()); 
         builder.appendHtmlConstant("<br /><b>Tweet: </b>"); 
         builder.appendEscaped(tweet.getText()); 
         builder.appendHtmlConstant("<br /><br />"); 
         resultsPanel.add(new HTML(builder.toSafeHtml())); 
        } 
        setLoading(false); 
       } 
      }); 
     } 
    }); 

    privacyPolicyButton = new Button("Privacy Policy"); 
    privacyPolicyButton.addClickHandler(new ClickHandler() { 
     @Override 
     public void onClick(ClickEvent event) { 
      setLoading(true); 
      service.getPrivacyPolicy(new AsyncCallback<String>() { 
       @Override 
       public void onFailure(Throwable caught) { 
        errorLabel.setText(caught.getMessage()); 
        errorLabel.setVisible(true); 
        setLoading(false); 
       } 

       @Override 
       public void onSuccess(String result) { 
        resultsPanel.clear(); 

        // convert newlines to <br /> 
        SafeHtmlBuilder builder = new SafeHtmlBuilder(); 
        builder.appendEscapedLines(result); 

        resultsPanel.add(new HTML(builder.toSafeHtml())); 

        setLoading(false); 
       } 
      }); 
     } 
    }); 

    resultsPanel = new VerticalPanel(); 

    errorLabel = new Label(); 
    errorLabel.addStyleName("errorLabel"); 
    errorLabel.setVisible(false); 

    //image from http://loadinfo.net/ 
    loadingImage = new Image("loading.gif"); 
    loadingImage.setVisible(false); 
} 

private void layoutWidgets() { 
    Panel panel = new VerticalPanel(); 

    panel.add(errorLabel); 

    Panel horizPanel = new HorizontalPanel(); 
    horizPanel.add(searchQueryTextBox); 
    horizPanel.add(searchButton); 
    horizPanel.add(privacyPolicyButton); 
    horizPanel.add(loadingImage); 
    panel.add(horizPanel); 

    panel.add(resultsPanel); 

    RootPanel.get().add(panel); 
} 

/** 
* Updates the UI for when a RPC call is made. 
* @param loading true if an RPC call is being sent, false if not 
*/ 
private void setLoading(boolean loading) { 
    if (loading) { 
     errorLabel.setVisible(false); 
    } 
    searchQueryTextBox.setEnabled(!loading); 
    searchButton.setEnabled(!loading); 
    privacyPolicyButton.setEnabled(!loading); 
    loadingImage.setVisible(loading); 
} 
} 

Oto ja s kod tweet:

package com.google.gwt.twittersearch.client; 

import java.io.Serializable; 

@SuppressWarnings("serial") 
public class Tweet implements Serializable{ 
private String id; 
    private String from_user; 
    private String created_at; 
    private String text; 

    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 

    public String getFrom_user() { 
     return from_user; 
    } 

    public void setFrom_user(String from_user) { 
     this.from_user = from_user; 
    } 

    public String getCreated_at() { 
     return created_at; 
    } 

    public void setCreated_at(String created_at) { 
     this.created_at = created_at; 
    } 

    public String getText() { 
     return text; 
    } 

    public void setText(String text) { 
     this.text = text; 
    } 


} 

Każdy wgląd w ten błąd lub miejsce, z którego mógłbym przejść, byłby bardzo ceniony!

Dzięki BRL

Odpowiedz

6

Trzeba dodać no-args konstruktora takich jak:

public class Tweet implements Serializable{ 

    public Tweet(){ 
    } 

} 

EDIT

Potrzebny będzie również jeden tutaj zbyt

private class SearchResponse { 

    public SearchResponse(){ 
    } 
    public List<Tweet> results; 
} 

, aby poradzić sobie z błędem java.lang.RuntimeException: Unable to invoke no-args constructor for class

zdefiniowana przez użytkownika klasa serializacji jeżeli:

  1. klasa przyporządkowuje się IsSerializable lub java.io.Serializable, albo dlatego, że wprowadza się te interfejsy, albo dlatego, że pochodzi od nadrzędnej który implementuje jeden z tych interfejsów.

  2. wszystkie klasy na non-końcowy, nie przemijające pola instancji są serializable

  3. klasa ma domyślny publiczny (zero argument) konstruktor

above is from this tutorial

+0

Hoepfully ja nie zrób coś głupiego, ale próbowałem tego i wciąż dostaję ten sam błąd.Próbowałem tego: 'public class Tweet implementuje Serializable { \t private String id; \t private String from_user; \t private String created_at; \t prywatny tekst ciągu; \t \t/** publicznego this (twit_id String twit_user String Ciąg twit_created, twit_text string) { \t * \t id = twit_id; \t * \t from_user = twit_user; \t * \t created_at = twit_created; \t * \t tekst = twit_text; \t} */ \t \t publicznego this() { \t \t \t} \t \t publicznego getId ciąg() { \t \t \t powrotu id; } 'i ja też wypróbowałem to z komentowaną częścią uncommented – brl8

+0

@ user1628648 zobacz moje edytowane komentarze. Potrzebujesz również konstruktora no-args dla SearchResponse. – user1258245