⬆️ ⬇️

Serialization of GWT RPC to the requested page for indexing the application by search engines and speeding up downloads

As you know, search engines do not like dynamically created pages, and the GWT page (application) is just dynamic.



In order for the search robot to be able to index some content, this content must be available in the html page at the time it is downloaded, and in typical GWT applications, content is requested from the server by an RPC request and forms an interface.

To circumvent this problem, a method of serializing the content that is requested from the server when the application loads is applied to the page.

An additional bonus of this method is to speed up the launch of the application, since no need to go to the server for data.



The principle of operation is:





Initial data.

Service:

 package com.oshift.ui.client.forummanamegemt; import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; import com.oshift.ui.shared.forum.GWTForum; import java.util.ArrayList; @RemoteServiceRelativePath("forummanagementservice") public interface ForumManagementService extends RemoteService { public ArrayList<GWTForum> getForums(); } 


')

Servlet:

 package com.oshift.ui.server.forummanamegemt; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import com.oshift.ui.client.forummanamegemt.ForumManagementService; import com.oshift.ui.shared.forum.GWTForum; import com.oshift.ws.db.forummanagement.Forum; import com.oshift.ws.db.forummanagement.Mapper; import com.oshift.ws.ejb.ForumManagerBean; import java.util.ArrayList; import javax.ejb.EJB; import javax.servlet.ServletException; public class ForumManagementServiceImpl extends RemoteServiceServlet implements ForumManagementService { public static ForumManagementServiceImpl instance = null; //    @Override public void init() throws ServletException { super.init(); instance = this; } //-    , ,   EJB @EJB private ForumManagerBean forumBean; @Override public ArrayList<GWTForum> getForums() { ArrayList<GWTForum> res = new ArrayList<GWTForum>(); for (Forum f : forumBean.getForums()) { GWTForum toGwt = Mapper.ForumMap.toGwt(f); res.add(toGwt); } return res; } } 




DTO objects for serialization:

* An important point is to get rid of the agony of SerializationPolicy settings, these objects implement the IsSerializable interface.

 package com.oshift.ui.shared.forum; import com.google.gwt.safehtml.shared.SafeHtml; import com.google.gwt.safehtml.shared.SafeHtmlUtils; import com.google.gwt.user.client.rpc.IsSerializable; import java.util.ArrayList; public class GWTForum extends GWTBootstrapDTO implements IsSerializable { public String forumName = " "; public ArrayList<GWTTopic> topics = new ArrayList<GWTTopic>(); public GWTForum() { } @Override public String getBootstrap() { String res = "Forum name: " + forumName + "<br>"; for (GWTTopic t : topics) { res += t.getBootstrap(); } //,     SafeHtml fromString = SafeHtmlUtils.fromString(res); return fromString.asString(); } } package com.oshift.ui.shared.forum; import com.google.gwt.safehtml.shared.SafeHtml; import com.google.gwt.safehtml.shared.SafeHtmlUtils; import com.google.gwt.user.client.rpc.IsSerializable; public class GWTTopic extends GWTBootstrapDTO implements IsSerializable { public String topicName = ""; @Override public String getBootstrap() { String res = " : " + topicName + "</br>"; SafeHtml fromString = SafeHtmlUtils.fromString(res); return fromString.asString(); } } 




Server side serialization process (for the sake of simplicity, directly in jsp):

 <%@page import="com.google.gwt.safehtml.shared.SafeHtmlUtils"%> <%@page import="com.oshift.ws.ejb.ForumManagerBean"%> <%@page import="javax.ejb.EJB"%> <%@page import="java.lang.reflect.Method"%> <%@page import="com.oshift.ui.client.forummanamegemt.ForumManagementService"%> <%@page import="com.google.gwt.user.server.rpc.RPC"%> <%@page import="java.util.ArrayList"%> <%@page import="com.oshift.ui.shared.forum.GWTForum"%> <%@page import="com.oshift.ui.server.forummanamegemt.ForumManagementServiceImpl"%> <%@page contentType="text/html" pageEncoding="UTF-8"%> <% //  ArrayList<GWTForum> forumsList = ForumManagementServiceImpl.instance.getForums(); //   Method m = ForumManagementService.class.getMethod("getForums"); //       - String forums = SafeHtmlUtils.fromString(RPC.encodeResponseForSuccess(m, forumsList)).asString(); //   noscript  StringBuilder noscriptSb = new StringBuilder(); for (GWTForum f : forumsList) { noscriptSb.append(f.getBootstrap()); } String noscript = noscriptSb.toString(); %> <!DOCTYPE html> <html> <head> <script type="text/javascript" language="javascript"> var forums='<%=forums%>'; </script> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Forums index</title> <link href="res/gfStyle.css" type="text/css" rel="stylesheet"/> <link href="res/login.css" type="text/css" rel="stylesheet"/> <meta name='gwt:module' content='com.oshift.ui.index=com.oshift.ui.index'> <script type="text/javascript" src="com.oshift.ui.index/com.oshift.ui.index.nocache.js"></script> </head> <body> ... <noscript> <%=noscript%> </noscript> 




Client side deserialization process:

 package com.oshift.ui.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.shared.GWT; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.SerializationException; import com.google.gwt.user.client.rpc.SerializationStreamFactory; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; import com.oshift.ui.client.forummanamegemt.ForumManagementServiceAsync; import com.oshift.ui.client.mainpage.ForumComposite; import com.oshift.ui.shared.forum.GWTForum; import java.util.ArrayList; public class IndexEntryPoint implements EntryPoint { // private final ForumManagementServiceAsync svc = ServicesFactory.getForumManagementServiceAsync(); @Override public void onModuleLoad() { //  unescape    String forums = new HTML(getForums()).getText(); SerializationStreamFactory ssf = (SerializationStreamFactory) svc; try { ArrayList<GWTForum> readObject = (ArrayList<GWTForum>) ssf.createStreamReader(forums).readObject(); for (GWTForum f : readObject) { //       process(f); } } catch (SerializationException ex) { //  Window.alert("       : " + ex); } ...    } //     private native String getForums()/*-{ return eval("$wnd.forums"); }-*/; } 




The content itself on the page looks like this:

 <!DOCTYPE html> <html> <head> <script type="text/javascript" language="javascript"> //  , . var forums='//OK[7,4,6,4,5,4,3,1,3,2,1,1,["java.util.ArrayList/4159755760","com.oshift.ui.shared.forum.GWTForum/1236332786","1","com.oshift.ui.shared.forum.GWTTopic/1653537274"," 1"," 2"," 3"],0,7]'; </script> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Forums index</title> <link href="res/gfStyle.css" type="text/css" rel="stylesheet"/> <link href="res/login.css" type="text/css" rel="stylesheet"/> <meta name='gwt:module' content='com.oshift.ui.index=com.oshift.ui.index'> <script type="text/javascript" src="com.oshift.ui.index/com.oshift.ui.index.nocache.js"></script> </head> <body> ... <noscript> Forum name: 1<br> :  1&lt;/br&gt; :  2&lt;/br&gt; :  3&lt;/br&gt; </noscript> </div> </body> </html> 




I hope my article will be useful to someone.

Source: https://habr.com/ru/post/163917/



All Articles