Rechercher dans ce blog

mercredi 2 mai 2012

16. Google app engine

Now that we have a platform web service working, we will make the back-end in order to return and store the yoctopuce output in the database. this part does not follow the traditional design patterns but instead show a PoC.

What is Google app engine? Google app engine is a framework provided by ... (you can guess!).

"Google App Engine lets you run web applications on Google's infrastructure. App Engine applications are easy to build, easy to maintain, and easy to scale as your traffic and data storage needs grow. With App Engine, there are no servers to maintain: You just upload your application, and it's ready to serve your users."

Google App engine configuration


To set google app engine (GAE) with Intellij Idea, the facet must be enabled during the project creation. It will create a default project structure with a particular file called appengine-web.xml. In particular the file will contain:

 
16    
17   <appengine-web-app xmlns="http://appengine.google.com/ns/1.0"> 
18       <application>yocto-meteo</application> 
19       <version>3</version> 
20       <static-files>

In this configuration file, the application and the version are used by the google infrastructure to determine the current version and application.

In order to use the database, we must describe how the database is accessed. This is described in META-INF/jdoconfig.xml.
 
13    
14   <jdoconfig xmlns="http://java.sun.com/xml/ns/jdo/jdoconfig" 
15              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
16              xsi:noNamespaceSchemaLocation="http://java.sun.com/xml/ns/jdo/jdoconfig"> 
17    
18       <persistence-manager-factory name="transactions-optional"> 
19           <property name="javax.jdo.PersistenceManagerFactoryClass" 
20                     value="org.datanucleus.store.appengine.jdo.DatastoreJDOPersistenceManagerFactory"/> 
21           <property name="javax.jdo.option.ConnectionURL" value="appengine"/> 
22           <property name="javax.jdo.option.NontransactionalRead" value="true"/> 
23           <property name="javax.jdo.option.NontransactionalWrite" value="true"/> 
24           <property name="javax.jdo.option.RetainValues" value="true"/> 
25           <property name="datanucleus.appengine.autoCreateDatastoreTxns" value="true"/> 
26       </persistence-manager-factory> 
27   </jdoconfig> 
28   

As soon as the Google app engine SDK is specified in Intellij Idea, you can run and debug your application using the standard UI.

Create the communication layer

For the communication layer, we would like to store the output of the YoctoHub and its localization in the database. For this purpose, Google provides a lot of help. The first step is to create an interface that specifies the functions that the server will support:


 
31    
32   @RemoteServiceRelativePath("worldmap") 
33   public interface WorldMapService extends RemoteService { 
34    
35       public void addMeteo(DataMeteo dataMeteo); 
36    
37       public List<DataMeteo> listMeteos(); 
38    
39       public void addHub(DataHub dataHub); 
40    
41       public List<DataHub> listHubs(); 
42    
43       public List<DataColor> listColors(); 
44    
45       public void addColor(DataColor color); 
46   } 
47   

This interface describes functions to list objects from database and add objects in the database. The annotation will help GAE to understand which URL must be managed by this service.

It is very important to understand that this interface (created on the client side) is used by the server. The interface used by the client will use asynchronous functions. Fortunately Intellij Idea creates such functions automatically, here is the interface that is created automatically:
 
24    
25   public interface WorldMapServiceAsync { 
26    
27       void addMeteo(DataMeteo dataMeteo, AsyncCallback<Void> async); 
28    
29       void listMeteos(AsyncCallback<List<DataMeteo>> async); 
30    
31       void listHubs(AsyncCallback<List<DataHub>> async); 
32    
33       void addHub(DataHub dataHub, AsyncCallback<Void> async); 
34    
35       void listColors(AsyncCallback<List<DataColor>> async); 
36    
37       void addColor(DataColor color, AsyncCallback<Void> async); 
38   }

On the client side, the code to call the service is the following:

private final WorldMapServiceAsync worldMapService = GWT.create(WorldMapService.class);

This will automatically create a AsyncService class that can be used out of the box.

On the server side, we implement the WorldMapService:

 
39    
40   public class WorldMapServiceImpl extends RemoteServiceServlet implements WorldMapService { 
41    
42    
43       private final Logger logger = Logger.getLogger(this.getClass().getName()); 
44    
45       private static final PersistenceManagerFactory PMF = 
46               JDOHelper.getPersistenceManagerFactory("transactions-optional"); 
47       private DAO<DataMeteo> meteoDAO; 
48       private DAO<DataHub> hubDAO; 
49       private DAO<DataColor> colorDAO; 
50    
51    
52       public WorldMapServiceImpl() { 
53           meteoDAO = new DAO<DataMeteo>(); 
54           hubDAO = new DAO<DataHub>(); 
55           colorDAO = new DAO<DataColor>(); 
56       } 
57    
58       // 
59       public void addMeteo(DataMeteo dataMeteo) { 
60           logger.info("Adding a new meteo in the Database"); 
61           meteoDAO.add(dataMeteo); 
62       } 
63    
64       public List<DataMeteo> listMeteos() { 
65           logger.info("Listing all the meteos"); 
66           return meteoDAO.list(DataMeteo.class); 
67       } 
68    
69       // 
70       private class DAO<T> { 
71           public List<T> list(Class clazz) { 
72               PersistenceManager pm = getPersistenceManager(); 
73               List<T> list; 
74               try { 
75                   Query q = pm.newQuery(clazz); 
76                   list = (List<T>) q.execute(); 
77    
78                   List<T> result = new ArrayList<T>(); 
79                   for (T dto : list) 
80                       result.add(dto); 
81                   logger.info("Server has fetched: " + result.size()); 
82                   return result; 
83               } finally { 
84                   pm.close(); 
85               } 
86           } 
87    
88           public void add(T dto) { 
89               PersistenceManager pm = getPersistenceManager(); 
90               try { 
91                   pm.makePersistent(dto); 
92               } finally { 
93                   pm.close(); 
94               } 
95           } 
96       }


What do we do here:
  • At line 45: we create the persistence manager with ID: "transactions-optional"
  • At line 59: the addMeteo function will call the DAO (declared at line 70) in order to save the add the object
  • At line 78: please note that we have to copy the objects in another list to avoid a JDO exception. 

That's all for the code! Everything is now ready to put the project in the google app engine infrastructure.

Upload your google app engine

Now that everything is working: Jenkins is successfully working and you have verified the web service is working, we can upload the application on the google infrastructure:

  1. Go in Tools->Upload App Engine Application

And that's all!!!

Warning: Do not store the GAE password in Intellij Idea and the Intellij Idea configuration file on GIT: it would mean your password (encrypted) will be stored in GIT.

Aucun commentaire:

Enregistrer un commentaire