Serialization GWT RPC in the requested page to be indexed by search engines apps and faster downloads

As is known, the search engines don't really like dynamically created pages, and page (application) GWT is dynamic.

So the crawler was able to index some content, this content must be accessible in the html page at the time it is loaded, and in a typical GWT application content is requested from the server by the RPC request and generates the interface.
To circumvent this problem can be applied a method of serialization in a page of content that is requested from the server when the application is loaded.
An added bonus of this method — speed up application start, because there is no need to go to the server data.

/ > The principle of operation is like this:
the
    the
  • To a DTO that is sent from the server, it adds an additional method(for example, by adding an abstract parent class that converts the content into a preferred form for search engines.
    the
    public abstract class GWTBootstrapDTO implements IsSerializable {
    
    public abstract String getBootstrap();
    }
    

  • the
  • in the formation of the host page on the server, a request is made to the servlet with the RPC interface and the received content is serialized (serialization later) directly in the page.
  • the
  • Then the generated page in the tag &ltnoscript&gt downloaded the content for indexing.
  • the
  • After the page has been received by the user starts the application, and all initial data deserialized from the host page.
  • the
  • Data for the search engines as there are in the page and available for indexing.


Original data.
Service:
the
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:
the
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;

//save a reference to the servlet
@Override
public void init() throws ServletException {
super.init();
instance = this;
}

//somehow need to receive data, for example, using 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;
}
}


Objects DTO for serialization:
*Important point for ridding yourself of MUK settings SerializationPolicy, these objects implement the IsSerializable interface.
the
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 = "just a forum";
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();
}
//escape, who knows what it
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 = "the Name of a topic:" + topicName + "</br>";
SafeHtml fromString = SafeHtmlUtils.fromString(res);
return fromString.asString();
}
}


The serialization process on the server side(for the sake of simplicity, directly in jsp):
the
<%@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 contentType="text/html" pageEncoding="UTF-8"%>

<%
//get the service
ArrayList<GWTForum> forumsList = ForumManagementServiceImpl.instance.getForums();
//get service method
Method m = ForumManagementService.class.getMethod("getForums");
//get the serialized screened content to insert in the host page
String forums = SafeHtmlUtils.fromString(RPC.encodeResponseForSuccess(m, forumsList)).asString();
//get the content of the noscript tag
NoscriptSb StringBuilder = 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='<%=content%>'; 
</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>


The deserialization process on the client side:
the
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.The 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 {

//Service
private final ForumManagementServiceAsync svc = ServicesFactory.getForumManagementServiceAsync();

@Override
public void onModuleLoad() {
//Unescape need to do for serialized content
String content = new HTML(getForums()).getText();
SerializationStreamFactory ssf = (SerializationStreamFactory) svc;
try {
ArrayList<GWTForum> readObject = (ArrayList<GWTForum>) ssf.createStreamReader(forums).the readObject();
for (GWTForum f : readObject) {
//do what we want with the received object
process(f);
}
} catch (SerializationException ex) {
//Error handling
Window.alert("unable to deserialize from the forums page to display:" + ex);
}
...continue to do what usually
}

//Get the serialized content from the page
private native String getForums()/*-{
return eval("$wnd.forums");
}-*/;
}


The content on the page looks like this:
the
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" language="javascript">
//this data seascale, believe me.
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>the Name of a topic: топик1&lt;/br&gt;the Name of a topic: топик2&lt;/br&gt;the Name of a topic: топик3&lt;/br&gt;
</noscript>
</div>
</body>
</html>


I hope my article will be useful to someone.
Article based on information from habrahabr.ru

Комментарии

Популярные сообщения из этого блога

Monitoring PostgreSQL + php-fpm + nginx + disk using Zabbix

Templates ESKD and GOST 7.32 for Lyx 1.6.x

Customize your Google