Create a new standard java project specifically to test the API we have developed in donation-service-play project.
Create a new Java Project in eclipse - this time neither a play nor an Android app, just a simple Java Application. Call the Project donation-service-play-test"
Now download this archive here:
Expand the archive and drag/drop the folder into your project. It should now look like this:
Select all of the imported jar files, right-click, and select 'Build Path->Add to Build Path'
The project should now be configured thus:
In donation-service-test, create a new package called 'app.donation.model'. Incorporate the following two classes into this package:
package app.donation.model;
public class User
{
public String _id;
public String firstName;
public String lastName;
public String email;
public String password;
public User(String firstName, String lastName, String email, String password)
{
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.password = password;
}
}
package app.donation.model;
public class Candidate
{
public String _id;
public String firstName;
public String lastName;
public String office;
public Candidate(String firstName, String lastName, String office)
{
this.firstName = firstName;
this.lastName = lastName;
this.office = office;
}
}
package app.donation.model;
public class Donation
{
public String _id;
public int amount;
public String method;
public Donation (int amount, String method)
{
this.amount = amount;
this.method = method;
}
}
These are java versions of the Mongoose javascript models we have developed in donaiton-web. Compare them now - can you see any differences?
In particular, look closely at Donation.
In donation-service-test, create a new package called 'app.donation.api'. Incorporate the following two classes into this package:
package app.donation.api;
import java.util.List;
import app.donation.model.Candidate;
import app.donation.model.Donation;
import app.donation.model.User;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Path;
public interface DonationService
{
@GET("/api/users")
Call<List<User>> getAllUsers();
@GET("/api/users/{id}")
Call<User> getUser(@Path("id") String id);
@POST("/api/users")
Call<User> createUser(@Body User User);
@GET("/api/donations")
Call<List<Donation>> getAllDonations();
@GET("/api/candidates")
Call<List<Candidate>> getAllCandidates();
@POST("/api/candidates/{id}/donations")
Call<Donation> createDonation(@Path("id") String id, @Body Donation donation);
}
package app.donation.api;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import app.donation.model.Candidate;
import app.donation.model.User;
import app.donation.model.Donation;
import retrofit2.Call;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class DonationServiceAPI
{
DonationService service;
public DonationServiceAPI(String url)
{
String service_url = url;
Gson gson = new GsonBuilder().create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(service_url)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
service = retrofit.create(DonationService.class);
}
public List<User> getUsers() throws Exception
{
Call<List<User>> call = (Call<List<User>>) service.getAllUsers();
Response<List<User>> users = call.execute();
return users.body();
}
public List<Candidate> getAllCandidates() throws Exception
{
Call<List<Candidate>> call = (Call<List<Candidate>>) service.getAllCandidates();
Response<List<Candidate>> candidates = call.execute();
return candidates.body();
}
public List<Donation> getAllDonations() throws Exception
{
Call<List<Donation>> call = (Call<List<Donation>>) service.getAllDonations();
Response<List<Donation>> donations = call.execute();
return donations.body();
}
public User createUser(User newUser) throws Exception
{
Call<User> call = (Call<User>) service.createUser(newUser);
Response<User> returnedUser = call.execute();
return returnedUser.body();
}
public Donation createDonation(Candidate candidate, Donation newDonation) throws Exception
{
Call<Donation> call = (Call<Donation>) service.createDonation(candidate._id, newDonation);
Response<Donation> returnedDonation = call.execute();
return returnedDonation.body();
}
}
Create another package called 'app.donation.test', and incorporate this class:
public class Main
{
static Gson gson = new GsonBuilder().setPrettyPrinting().create();
public static void println(Object o)
{
System.out.println(gson.toJson(o));
}
public static void println(String s)
{
System.out.println(s);
}
public static void main(String[] args) throws Exception
{
DonationServiceAPI service = new DonationServiceAPI("http://localhost:4000");
List<Candidate> candidates = service.getAllCandidates();
List<User> users = service.getUsers();
List<Donation> donations = service.getAllDonations();
println ("--------------------");
println (" all users: ");
println ("--------------------");
println(users);
println ("--------------------");
println (" all candidates: ");
println ("--------------------");
println(candidates);
println ("--------------------");
println (" all donations: ");
println ("--------------------");
println(donations);
}
}
Make sure Mongod + donation-web are running, and execute this main program now. It should print the following to the console:
--------------------
all users:
--------------------
[
{
"_id": "58159f0d776b3c73f442f65a",
"firstName": "Homer",
"lastName": "Simpson",
"email": "homer@simpson.com",
"password": "secret"
},
{
"_id": "58159f0d776b3c73f442f65b",
"firstName": "Marge",
"lastName": "Simpson",
"email": "marge@simpson.com",
"password": "secret"
},
{
"_id": "58159f0d776b3c73f442f65c",
"firstName": "Bart",
"lastName": "Simpson",
"email": "bart@simpson.com",
"password": "secret"
}
]
--------------------
all candidates:
--------------------
[
{
"_id": "58159f0d776b3c73f442f65d",
"firstName": "Lisa",
"lastName": "Simpson",
"office": "President"
},
{
"_id": "58159f0d776b3c73f442f65e",
"firstName": "Donald",
"lastName": "Simpson",
"office": "President"
}
]
--------------------
all donations:
--------------------
[
{
"_id": "58159f0d776b3c73f442f65f",
"amount": 40,
"method": "paypal"
},
{
"_id": "58159f0d776b3c73f442f660",
"amount": 90,
"method": "direct"
},
{
"_id": "58159f0d776b3c73f442f661",
"amount": 430,
"method": "paypal"
},
{
"_id": "58159f13776b3c73f442f662",
"amount": 5000,
"method": "paypal"
}
]
Think carefully about what we have just done.
However, our client is Java, not Javascript. These classes we have produced here will be ideal starting points for building out the Android classes we need to hook up the donation-andoid app to the donation-web service.
Try this at the end of the main method:
Donation donation = new Donation(5000, "paypal");
service.createDonation(candidates.get(0), donation);
donations = service.getAllDonations();
println ("--------------------");
println (" all donations with a new donation created: ");
println ("--------------------");
println(donations);
We are trying to create a donation. Our output should show the new donation at the end:
{
"_id": "5815a8bf0dc72a79a540cf20",
"amount": 5000,
"method": "paypal"
}
Check the web app to see if it was created.
Looking again at the donation model:
public class Donation
{
public String _id;
public int amount;
public String method;
public Donation (int amount, String method)
{
this.amount = amount;
this.method = method;
}
}
.. and the equivalent mongoose model:
const donationSchema = mongoose.Schema({
amount: Number,
method: String,
donor: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
candidate: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Candidate',
},
});
We can see we are missing the references to donor and candidate.
Include a new class in our java project now :
package app.donation.model;
public class DonationComplete
{
public String _id;
public int amount;
public String method;
public User donor;
public Candidate candidate;
public DonationComplete (int amount, String method)
{
this.amount = amount;
this.method = method;
}
}
It is identical to the previous version, except we have added references to donor and candidate. These references are using the Java User and Candidate classes we have already defined.
We will use this class in parellel with the existing simpler Donation class. First, include a new method in DonationService:
@GET("/api/donations")
Call<List<DonationComplete>> getAllCompleteDonations();
Then extend DonationServiceAPI with this new method:
public List<DonationComplete> getAllCompleteDonations() throws Exception
{
Call<List<DonationComplete>> call = (Call<List<DonationComplete>>) service.getAllCompleteDonations();
Response<List<DonationComplete>> donations = call.execute();
return donations.body();
}
At the end of our main method, try to read and print all donations:
println ("--------------------");
println (" complete donations: ");
println ("--------------------");
List<DonationComplete> complateDonations = service.getAllCompleteDonations();
println(complateDonations);
At the tail end of the console output, we see the complete donations, including the donor & candidate references:
[
{
"_id": "5815a5b10dc72a79a540cf1d",
"amount": 40,
"method": "paypal",
"donor": {
"_id": "5815a5b00dc72a79a540cf1a",
"firstName": "Bart",
"lastName": "Simpson",
"email": "bart@simpson.com",
"password": "secret"
},
"candidate": {
"_id": "5815a5b00dc72a79a540cf1b",
"firstName": "Lisa",
"lastName": "Simpson",
"office": "President"
}
},
{
"_id": "5815a5b10dc72a79a540cf1e",
"amount": 90,
"method": "direct",
"donor": {
"_id": "5815a5b00dc72a79a540cf19",
"firstName": "Marge",
"lastName": "Simpson",
"email": "marge@simpson.com",
"password": "secret"
},
"candidate": {
"_id": "5815a5b00dc72a79a540cf1b",
"firstName": "Lisa",
"lastName": "Simpson",
"office": "President"
}
},
{
"_id": "5815a5b10dc72a79a540cf1f",
"amount": 430,
"method": "paypal",
"donor": {
"_id": "5815a5b00dc72a79a540cf18",
"firstName": "Homer",
"lastName": "Simpson",
"email": "homer@simpson.com",
"password": "secret"
},
"candidate": {
"_id": "5815a5b10dc72a79a540cf1c",
"firstName": "Donald",
"lastName": "Simpson",
"office": "President"
}
},
{
"_id": "5815a8bf0dc72a79a540cf20",
"amount": 5000,
"method": "paypal",
"candidate": {
"_id": "5815a5b00dc72a79a540cf1b",
"firstName": "Lisa",
"lastName": "Simpson",
"office": "President"
}
}
]
Archive of the the project so far:
Introduce an endpoint that retrieves all donations for a specific candidate, and extend main to exercise it
Experiment with accessing a deployed version of the API.