Total Noob to gwt/gson in eclipse, error: "Unable to invoke no-args constructor for class"
You need to add a no-args constructor such as:
public class Tweet implements Serializable{
public Tweet(){
}
}
EDIT
You will also need one here too
private class SearchResponse {
public SearchResponse(){
}
public List<Tweet> results;
}
to deal with your error java.lang.RuntimeException: Unable to invoke no-args constructor for class
A user defined class is serializable if:
the class is assignable to IsSerializable or java.io.Serializable, either because it implements one of these interfaces, or because it is derived from a superclass that implements one of these interfaces.
all the class’s non-final, non-transient instance fields are serializable
the class has a public default (zero argument) constructor
brl8
Updated on June 11, 2022Comments
-
brl8 almost 2 years
I'm playing around with this Google Web toolkit/GSON example that gets data from twitter.
Everything is compiling just fine, but when I debug as Web Application, everything loads just fine, but when I click the "search" button I get the following error:
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
Here is the TwitterServiceImpl code:
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; } }
Here is the entry point code:
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); } }
Here is the tweet code:
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; } }
Any insight into this error or where I might go from here would be greatly appreciated!
Thanks, brl
-
brl8 over 11 yearsHoepfully I did not do something stupid but I tried this and I'm still getting the same error. I tried this:
public class Tweet implements Serializable{ private String id; private String from_user; private String created_at; private String text; /** public Tweet(String twit_id, String twit_user, String twit_created, String twit_text){ * id = twit_id; * from_user = twit_user; * created_at = twit_created; * text = twit_text; } */ public Tweet() { } public String getId() { return id; }
and I also tried it with the commented part uncommented -
user1258245 over 11 years@user1628648 see my edited comments. You also need a no-args constructor for SearchResponse.