Skip to content

Commit

Permalink
First try at threading, more DOCS
Browse files Browse the repository at this point in the history
  • Loading branch information
Nicolas Arkkila committed Dec 9, 2013
1 parent a6fe4d3 commit b659816
Show file tree
Hide file tree
Showing 25 changed files with 438 additions and 413 deletions.
9 changes: 3 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
jlab - Flavour of the Now (formerly Month)
jlab - Flavour of the Now
====

University of Helsinki Java assignment for "Javalabra 2013"
Expand All @@ -16,10 +16,7 @@ To run the app, simply clone the source and run the following in jlab/:
$ mvn clean package
$ java -jar target/dependency/jetty-runner.jar <--port {number}> target/<war package>.war
```

By default, the app runs at port 8080, so use localhost:8080. By specifying --port before the .war package, you can run it at any available port. Maven Jetty plugin is also included, so you can use mvn jetty:run as well.
After jetty-runner is launched, open your browser at localhost:8080.
By specifying --port before the .war package, you can run it at any available port. Maven Jetty plugin is also included, so you can use mvn jetty:run as well.

If you need to test the app, you can register an app @ https://dev.twitter.com/

TO-DO:

1 change: 1 addition & 0 deletions doc/HOURS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@
5.11.2013 - 14-16 Spring, UI styling, documentation
8.11.2013 - 22-24 Coding, UI styling
9.11.2013 - 12-13 Coding
9.11.2013 - 18-24 Coding, testing, JavaDoc+other documents, final touches
17 changes: 17 additions & 0 deletions doc/classStructure.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
The class structure is as follows:

# FotmServlet (in Servlet)
FotmServlet is the user-facing class. It handles all requests.
It also contains the TwitterEvaluator service and the TwitterHistory repository, to which it communicates. It passes data to TwitterHistory for caching.

# TwitterHistory (in Repo)
Simply a list repository of cached tweets. It gives results based on the repository status, such as latest result, this month's favourite, and can return a list for other classes to use. Uses TwitterCache objects to store into the cache.

# TwitterEvaluator implements EvaluatorService (in Service)
This class is responsible for communicating with the Twitter API. It sends requests, gets responses and sends the responses for evaluation to TwitterCrunch. It passes data as a String object further to the servlet.

#TwitterCrunch (in Logic)
This class is a helper class for TwitterEvaluator, to determine which hashtag is the top trending #1 of a list of hashtags, based on their latest 100 tweets. Only TwitterEvaluator has access to this class.

#TwitterCache (in Data)
A simple datatype to store a hashtag and a Date when the cache was set. Used in TwitterHistory.
10 changes: 10 additions & 0 deletions doc/description.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Flavour of the Now (jlab) was a University of Helsinki Java assignment for "Javalabra 2013".

Need to use a database for your program? This app will tell you which one to choose.
Flavour of the Now (FOTN) parses Twitter feeds to determine what is your database of choice. The base functionality of the app is built upon the Twitter API 1.1, and it uses the twitter4j library.

FOTN gets a list of hashtags with a list of their tweets, and calculates which one is the top #1 trending of the bunch, which is then returned to the user. These results are then cached for later requests, and a new Twitter API request is not made until the cache times out.

Users consists of anyone making a request. In this version, users only make requests and receive a view based on the result.

Of course, while the results are accurate, you should not take the descriptions of the features seriously, they are meant to be satire :).
8 changes: 8 additions & 0 deletions doc/instructions.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Instructions
If you do not have Maven, download it. You can also use a bundled Maven if you use some IDE like NetBeans. You can run the app through the IDE as well, if you have a server like Tomcat installed.

If you already have Maven, to run the app, you need simply clone the source and run the following in jlab/:
$ mvn clean package
$ java -jar target/dependency/jetty-runner.jar <--port {number}> target/<war package>.war

After jetty-runner is launched (you see SelectChannelConnector@0.0.0.0:8080 STARTING), open your browser at localhost:8080.
20 changes: 20 additions & 0 deletions doc/testDoc.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Test Documentation
====

There were some challenges regarding testing. At first, while I was building the servlet, I didn't have a lot of tests, because there was no real core logic. After familiarising myself with the Twitter API, I had to quickly jump into the testing section, which helped me greatly in the end.

Lots of things in Spring had to be tested by hand.

# CrunchTest
Testing saved lots of time in this class. I did have another Java program just to test the number crunching coming from the Twitter API, but with unit tests I was able to build reliable methods to determine the trending hashtag. I also had to create a TestStatus class to be able to test this class, since the base Status class from twitter4j did not have a mutable Status class.

The final test (when scores collide up until timescores) is based on randomness, so I left that untested and did it by hand. I did get variable (that is, random) results on it nevertheless.

# HistoryTest
I was having some odd in this class before fixing it with unit tests. The core logic of this class is a lot simpler, so there is not that much to test.

# ServletTest
As there is not much going on on the view side, just testing if the servlet launches properly was the only thing of use I could really think of, since otherwise there would be a system issue the admin would have to review.

# CacheTest
Once again, a very simple class with just actually a string and a Date object. Mostly to just test whether they are set correctly.
8 changes: 7 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,13 @@
<artifactId>ini4j</artifactId>
<version>0.3.3</version>
</dependency>

<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-htmlunit-driver</artifactId>
<version>2.35.0</version>
<scope>test</scope>
<type>jar</type>
</dependency>
</dependencies>


Expand Down
49 changes: 33 additions & 16 deletions src/main/java/wad/jlab/data/TwitterCache.java
Original file line number Diff line number Diff line change
@@ -1,37 +1,39 @@
package wad.jlab.data;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import twitter4j.Status;

/**
* Simple data class to store the latest winning result.
* Use to avoid getting rate-limited.
* @param hashtag Simply provide the hashtag. Everything else is generated.
*/
public class TwitterCache {

@Value("${message}")
/**
* The hashtag as a string, with leading hash.
*/
private String hashtag;
/**
* The date when this cache entry was created.
*/
private Date dateFetched;
private Date formattedDate;
/**
* These two are just to enable testing by hand if you need them.
*/
private int cacheTimeout = 5;
private int cacheTime = 0;
private List<Status> tweets;

public TwitterCache(String hashtag) {
this(hashtag,new ArrayList());
}

public TwitterCache(String hashtag, List<Status> tweets) {
/**
* Constructs the new cache and sets a date to it. Cachetime is for testing if needed.
* @param hashtag as a string object.
*/
public TwitterCache(String hashtag) {
this.hashtag=hashtag;
this.dateFetched = Calendar.getInstance().getTime();
this.tweets=tweets;
this.cacheTime+=1;
}


public int getCacheTimeout() {
return cacheTimeout;
Expand All @@ -44,15 +46,26 @@ public void setCacheTimeout(int cacheTimeout) {
public int getCacheTime() {
return cacheTime;
}

/**
* Increments the current cachetime.
*/
public void incrementCacheTime() {
this.cacheTime+=1;
}

/**
* To access the locale properties we pass a substring by default to the servlet.
*
* @return String the hashtag without leading hash.
*/
public String getHashtag() {
return hashtag.substring(1); //return plaintext answer to simplify styling
}

/**
* Returns the hashtag with leading hash. This is used for caching purposes in the history level.
* @return String hashtag with leading hash.
*/
public String getHashtagWithHash() {
return hashtag;
}
Expand All @@ -65,12 +78,16 @@ public Date getDateFetched() {
return dateFetched;
}

//change into f ull hour timeout
/**
* Returns whether the cache has timed out or not.
* Currently checks if over an hour has passed since the last query. This is to avoid getting rate-limited.
* @return boolean timeout value.
*/
public boolean hasTimedOut() {
//return true; // enable to test per hand
Calendar cachetime = Calendar.getInstance();
cachetime.setTime(dateFetched);
return cachetime.get(Calendar.MINUTE) != Calendar.getInstance().get(Calendar.MINUTE);
return cachetime.get(Calendar.HOUR_OF_DAY) != Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
}


Expand Down
Loading

0 comments on commit b659816

Please sign in to comment.