x-traveler

35
X- TRAVELER Sixiang Chen, Shuli Shi, Xiaoping Li, Yinan Zhao, Shaojie Chen Group 14

Upload: wilma

Post on 25-Feb-2016

45 views

Category:

Documents


0 download

DESCRIPTION

X-Traveler. Sixiang Chen, Shuli Shi, Xiaoping Li, Yinan Zhao, Shaojie Chen Group 14. Contents. Overview Architecture : Client Side Architecture: Server Side Pains & Gains Future Work Demos. Overview. X-Traveler is a mobile application on the android platform - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: X-Traveler

X-TRAVELE

RSixiang Chen, Shuli Shi, Xiaoping

Li, Yinan Zhao, Shaojie ChenGroup 14

Page 2: X-Traveler

Overview Architecture: Client Side Architecture: Server Side Pains & Gains Future Work Demos

Contents

Page 3: X-Traveler

X-Traveler is a mobile application on the android platform

Allows people to search and share information about different tourist sites like national parks

~100 classes and ~10000 lines of codes The codes are well refactored for further development Major use cases have been implemented: Login,

Register, Search for Attraction Place, View Attraction Place Details, Open Personal Page, Add To Wishlist, Create Travel Plan

Overview

Page 4: X-Traveler

Partially Implemented Extension Features: Add Friends

Extension Features To Be Implemented: Invite Friends to Comment on Plan, Recommend User with Similar Interests

Overview

Page 5: X-Traveler

Use Cases Review: Basic:

Login, Signup, Search for Place, Open Personal Page, Add to Wish list, Add to Visited List, Create Travel

Plan Extension:

Recommend Friend, Recommend Place, Add friend, Comment on Travel Plan

Overview

Page 6: X-Traveler

The Architecture:

Overview

Client Side

Database(MySQL)

ORM

JVM

Hibernate

SocketJSONObjectApach

eMysql

Php

Page 7: X-Traveler

Architecture: Client Side

UI Viewres

xml

ModelUserinterface.packageActivity

Utility ClassUtil.package

SocketHelper

HttpHelper

CommandCommand.package

Interface:

Request

Response

Page 8: X-Traveler

UI Pages:

Client Side: UI Views

Login

Signup

Main Page

Personal Page

Find Place City

Placewishlistvisitedlist

Page 9: X-Traveler
Page 10: X-Traveler

Each Activity corresponds to a page in the app

public class LogInActivity extends Activity {TextView test;

Handler mHandler;……signupButton = (Button)findViewById(R.id.signup);

signupButton.setOnClickListener(new OnClickListener(){ public void onClick(View arg0) { Request req = new SignUpRequest(username.getText().toString(),password.getText().toString() ); jsonobj = req.getJSON(); new ConnectServerThread().start();

// Option: new Task().excute();}

});

Client Side: Model

Page 11: X-Traveler

Open a new thread to connect with Server-Sideclass ConnectServerThread extends Thread {

public void run() { try {

helper.sendJSONToServer(jsonobj);Message msg = mHandler.obtainMessage(); msg.obj = helper.getUTFFromServer(); JSONObject resJSON = helper.toJSON(msg.objString response = (String)

resJSON.get(keys.RES_LOGIN_ACT); if (response.equals(values.LOGIN_SUC) || response.equals(values.SIGN_UP_SUC)) {

/* Switch to next page */ Response res = new LoginSucResponse(); res.run(LogInActivity.this, MainPage.class); } else {

mHandler.sendMessage(msg); }

Client Side: Model

Page 12: X-Traveler

Handling different actions according to different response from Server

class MessageHandler extends Handler {@Overridepublic void handleMessage(Message msg) {try {

String response = (helper.toJSON(msg.obj)).toString(); if (response.equals(values.SIGN_UP_INVALID_INPUT)){ test.setText("Invalid username or password to sign up."); } else if (response.equals(values.SIGN_UP_USERNAME_DUP)){test.setText("Username exists. Please select another one."); } else if

… }

} catch (JSONException e) {// TODO Auto-generated catch block e.printStackTrace();

Client Side: Model

Page 13: X-Traveler

Each Activity corresponds to a page in the app

public class LogInActivity extends Activity {TextView test;

Handler mHandler;……signupButton = (Button)findViewById(R.id.signup);

signupButton.setOnClickListener(new OnClickListener(){ public void onClick(View arg0) { Request req = new SignUpRequest(username.getText().toString(),password.getText().toString() ); jsonobj = req.getJSON(); new ConnectServerThread().start();

// Option: new DownloadFileTask().excute();}

});

Client Side: Model

Page 14: X-Traveler

class DownloadFileTask extends AsyncTask<Void, Void, Void> {@Overridepublic void onPostExecute(Void result) { wishlistImageViews[1].setImageBitmap(downloadImages[1]);…}@Overrideprotected Void doInBackground(Void... params) {// Connect with Server and get feedbackHttpUtil httpUtil = new HttpUtil……InputStream inputStream = httpUtil.getInputStream();downloadImages[2] = BitmapFactory.decodeStream(inputStream);……}

Client Side: Model

Page 15: X-Traveler

Two ways to connect with outside resources Server: Socket

// 10.0.2.2 for the emulator // IPv4 connect in same wifi network socket = new Socket("10.164.238.14", 4415); dos = new DataOutputStream( socket.getOutputStream()); dos.writeUTF(req.toString());…dis = new DataInputStream( socket.getInputStream()); return dis.readUTF()

Images: HTTP httpURLConnection = (HttpURLConnection) url.openConnection(); // Set time out httpURLConnection.setConnectTimeout(3000);httpURLConnection.setRequestMethod("GET");……

Client Side: Utility Classes

Page 16: X-Traveler

Storage Options Shared Preferences Internal Storage SQLite Databases

Client Side: Utility Classes

Page 17: X-Traveler

Store user information locally:

/*Store session key/ username into USER_INFOS.XML*/SharedPreferences infos = getSharedPreferences(USER_INFOS, 0);infos.edit() .putString(NAME, username.getText().toString()) .commit(); /*Get session key from USER_INFOS.XML*/Sessionkey = getSharedPreferences(JsonKeys.USER_INFOS, 0).getString(JsonKeys.SESSION_KEY,””)

Client Side: Utility Classes

Page 18: X-Traveler

Overview:

Architecture: Server Side

MySQL

Hibernate

DAO Layer

Session Comma

nd

Open Comma

nd

PersonalPage

Command Factory

Login Command

Factory

Client Handler

Socket Manage

r

Server

GeneralComman

dFactory

Interface:Comman

d

Interface:Command

Factory

Page 19: X-Traveler

SessionKey Communication:

Architecture: Server Side

SessionKey is a randomly generated

character string of length 32(62^32)

Client 1

Client k

Server

Database

1 Signup/Login (id + pw)2 SessionKey (or fail)3 SessionKey + new request4 Respond (or sessionout)

Page 20: X-Traveler

Socket Manager:public class SocketManager {

public SocketManager(SessionFactory sessionFactory) {/** constructor code **/}

public void createSocketManager(Scanner inputPortNumber) throws IOException, JSONException {int cur_port = inputPortNumber.nextInt();serverSocket = new ServerSocket(cur_port);while (true) {try {System.out.println("S: Receiving...");socket = serverSocket.accept();ClientHandler clientHandler = new ClientHandler(socket, sessionFactory);// This thread will do the talkingThread t = new Thread(clientHandler);t.start(); } catch (IOException ioe) { System.out.println("IOException on socket listen: " + ioe);

ioe.printStackTrace(); }}

}

Architecture: Server Side

ClientHandler Connects Network

(socket) with database (sF)

Page 21: X-Traveler

Client Handler:

public class ClientHandler implements Runnable {private Socket socket;private SessionFactory sessionFactory;public ClientHandler(Socket s, SessionFactory sessionFactory) {

this.socket = s;this.sessionFactory = sessionFactory; }

public void run() {GeneralCommandFactory generalCommandFactory = new GeneralCommandFactory();ExecutionContext context = new ExecutionContext(sessionFactory, new UserDAO(sessionFactory), new PlaceDAO(sessionFactory), new PlanDAO(sessionFactory));try {DataInputStream dis = new DataInputStream(socket.getInputStream()); JSONObject jsonObject = new JSONObject(dis.readUTF());// call exception to deal with illegal purpose commandCommand command = generalCommandFactory.create(jsonObject);DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); JSONObject response = command.execute(context);dos.writeUTF(response.toString()); } catch (IOException | JSONException | CommandException| NullPointerException e) { e.printStackTrace();}}

}

Architecture: Server Side

OCP / DRY Principles

Context: Necessary Execution

Environment

Page 22: X-Traveler

ExecutionContextpublic class ExecutionContext {

private SessionFactory sessionFactory;private UserDAO userDAO;private PlaceDAO placeDAO;private PlanDAO planDAO;…../** Contains all execution requirement **/

}

Architecture: Server Side

OCP Principle

Page 23: X-Traveler

Command Factory: (Factory Pattern & Singleton Pattern)

public class GeneralCommandFactory {JSONObject jsonObject;/** * FACTORISE contains all concrete command factories */private static final CommandFactory[] FACTORIES = { new LoginCommandFactory(),

new SignUpCommandFactory(),new LogOutCommandFactory(), new AddVisitedPlaceCommandFactory(),new AddWishListPlaceCommandFactory(), newSearchPlaceCommandFactory(), new

GetVisitedListCommandFactory(), new GetWishListCommandFactory(), new PersonalPageCommandFactory(), new ListPlaceDetailCommandFactory(), new

ListFriendFactory(), new AddFriendFactory(), new DeleteFriendFactory(), new ShowCommonInterestUserFactory(), new UpdateUserInfoFactory(), new WritePlanFactory(), new PlanCommentFactory() };

private Map<String, CommandFactory> factoryMap;public GeneralCommandFactory() {this.factoryMap = new HashMap<>();for (CommandFactory factory : FACTORIES) {

this.factoryMap.put(factory.getCommandName(), factory); } }

Architecture: Server Side

Singleton Pattern

Page 24: X-Traveler

Command Factory: (Factory Pattern & Singleto Pattern)

/** * pass the json object to each concrete command factory * @param jsonObject * @return Command * @throws JSONException * @throws CommandException */public Command create(JSONObject jsonObject) throws JSONException, CommandException {

Command command = null; String commandName = jsonObject.getString(JsonKeys.PURPOSE);System.out.println(commandName);CommandFactory factory = this.factoryMap.get(commandName);if (factory == null) {// TODO: replace with an exception type that the caller can handle // (probably ProtocolException) System.out.println("void");throw new CommandException("no such command exist");} else {command = factory.makeCommand(jsonObject);return command; } }}

Architecture: Server Side

Page 25: X-Traveler

Session Command & Open Command:(Command Pattern)public abstract class SessionCommand implements Command {

JSONObject j;public SessionCommand(JSONObject j) {

this.j = j; }public boolean executeAuthenticated() throws CommandException, JSONException {/* Code to Anthenticate With SessionKey */}

}

public interface OpenCommand extends Command {}

Architecture: Server Side

Page 26: X-Traveler

Hibernate: DAO Layerpublic class PlaceDAO {

public PlaceDAO(SessionFactory sessionFactory) {}public void insertPlace(/* args */) {}public Place getPlace(/* args */) {}public String getPlaceImage(/* args */) {}public int getPlaceRate(/* args */) {}public void addToWishList(/* args */){}…

}

Architecture: Server Side

Page 27: X-Traveler

Hibernate DAO Layer: Template Methodpublic abstract class TransactionRoutine<P, R, X extends Exception> {…..public abstract R executeWithinTransaction(Session session, Transaction transaction, P param) throws X;public R execute(P param) throws X {

Session session = sessionFactory.getCurrentSession();boolean startedTransaction = false;Transaction tx = THREAD_TX.get();if (tx == null) {tx = session.beginTransaction();THREAD_TX.set(tx);startedTransaction = true;} try {R r = executeWithinTransaction(session, tx, param); if (startedTransaction) {tx.commit();THREAD_TX.set(null);}return r; } catch (Throwable t) {if (startedTransaction) {tx.rollback();THREAD_TX.set(null); }throw t;}

}}}

Architecture: Server Side

Page 28: X-Traveler

Hibernate DAO Layer: Template Methodpublic class PlaceDAO {…..public Place getPlace(String placeName) {TransactionRoutine<String, Place, RuntimeException> routine = new TransactionRoutine<String, Place, RuntimeException>(this.sessionFactory) {

@Overridepublic Place executeWithinTransaction(Session session, Transaction tx, String

placeName) {Query query = session.createQuery("from Place where placename=:placename");query.setParameter("placename", placeName); List<Place> list = query.list();for (Place u : list) {return u;}return null; }};return routine.execute(placeName);

}}

Architecture: Server Side

the Hollywood Principle!

Page 29: X-Traveler

Hibernate: ThreadLocalpublic class HibernateUtil { public static final ThreadLocal local = new ThreadLocal ();

public static Session currentSession() throws HibernateException { Session session = (Session) local.get(); //open a new session if this thread has no session if(session == null) { session = sessionFactory.openSession(); local.set(session);

}

return session;}

}

Architecture: Server Side

ThreadLocal(): create a thread local variable

get(): return the session / value of

threadlocal variable

Purpose: avoid multiple sessions

in a single thread

Page 30: X-Traveler

Hibernate: In hibernate configuration file, <property name = “hbm2ddl.auto”> create </property> can clear the whole (previous) database But when there are changes in the foreign keys of one

table (or related constraints), Hibernate may not delete them automatically.

We then have to delete the database by hand and recreate

it

Architecture: Server Side

Page 31: X-Traveler

A lot of time is spent struggling with Git But finally figured out how it works Writing our own sockets manager takes more

time and codes We have more flexibility with our own socket

manager Server side code is structurally refactored on

Iteration 4 Finally got a clearly (hierarchically) structured

server side and classes with efficient inheritance

Pains & Gains

Page 32: X-Traveler

Pains & GainsOld Structure:

MySQL

Hibernate

DAO Layer

PersonalPage

Command

Login Command

Client Handler

Socket Manage

r

Server

Command

Factory

Interface:Comman

d Potential Conflict Among

multiple Users

Page 33: X-Traveler

Implement two extension features and use Facebook API

Add more detailed controls on steps such as password strength and etc.

Refine the java doc Further machine tests with tools such as

Monkey Test Test app online and get User Experience

feedbacks

Future Work

Page 34: X-Traveler

Extension Feature: Friend Recommendation Currently we are using a simple comparison

method: for two arbitrary users, we use the number of shared visited places and wish-to-go places as a similarity score

When the number of users get large, we could use some more efficient clustering algorithms such as k-means

For place recommendation, we will use a similar logic with social network data: compared a person’s friends with the group of people who have been to a place as a recommendation score

Future Work

Page 35: X-Traveler

Thanks to Professor Smith and all TAs for this excellent class!

Thanks to Jed and Zach for your patience and help in solving the different problems we ran into!

Thanks to Our team members, Group 14 is an awesome team!

Thanks!