I have amethod which returns the SSID of the strongest WiFi acces point. Tha data for the mapping is in file names"ssid_number.txt" in the raw folder. How can I parse this file in my case with GSON library to get the number 4 if the strongest WiFi access point"KD WLAN Hotspot" is?
{
"KD Privat": 1,
"KD WLAN Hotspot": 4,
"treeWifi": 9,
"cafeWifi": 5 //I have here more that 200 WIFI access point
}
I did it the next way.
I had JSON string pulled from a url. Then,
Gson gson = new Gson(); // create Gson obj
currentResponse = gson.fromJson(resultJSON, City.class);
currentResponse is a json.toString() output.
Next, create new class for your json output with all fields corresponding to json. Look at my working code:
public class City {
#SerializedName("name")
public String cityName;
public String getCityName() {
return cityName;
}
}
In your case it would be like:
public class WiFi {
#SerializedName("cafeWifi")
public int wiFiAmount;
public int getWiFiAmount() {
return wiFiAmount;
}
}
Get your wifi amount by this method:
WiFi wifi = new WiFi();
int a = wifi.getWiFiAmount();
Looking at your data it seems your identifiers are not constant.
In this case it would work if you use a typemap. So something like this:
HashMap<String, Integer> mMap = null;
Type type = new TypeToken<HashMap<String, Integer>>() {}.getType();
mMap = new Gson().fromJson(json, type);
Create POJO for your json response.
public class JsonResponsePojo {
#SerializedName("KD Privat")
#Expose
private Integer KDPrivat;
#SerializedName("KD WLAN Hotspot")
#Expose
private Integer KDWLANHotspot;
#Expose
private Integer treeWifi;
#Expose
private Integer cafeWifi;
/**
*
* #return
* The KDPrivat
*/
public Integer getKDPrivat() {
return KDPrivat;
}
/**
*
* #param KDPrivat
* The KD Privat
*/
public void setKDPrivat(Integer KDPrivat) {
this.KDPrivat = KDPrivat;
}
/**
*
* #return
* The KDWLANHotspot
*/
public Integer getKDWLANHotspot() {
return KDWLANHotspot;
}
/**
*
* #param KDWLANHotspot
* The KD WLAN Hotspot
*/
public void setKDWLANHotspot(Integer KDWLANHotspot) {
this.KDWLANHotspot = KDWLANHotspot;
}
/**
*
* #return
* The treeWifi
*/
public Integer getTreeWifi() {
return treeWifi;
}
/**
*
* #param treeWifi
* The treeWifi
*/
public void setTreeWifi(Integer treeWifi) {
this.treeWifi = treeWifi;
}
/**
*
* #return
* The cafeWifi
*/
public Integer getCafeWifi() {
return cafeWifi;
}
/**
*
* #param cafeWifi
* The cafeWifi
*/
public void setCafeWifi(Integer cafeWifi) {
this.cafeWifi = cafeWifi;
}
}
Read wifi -HotSpot
Gson gson=new Gson();
JsonResponsePojo data=gson.fromJson(responseString, JsonResponsePojo.class);
String kdWLanHotSpot=data.getKDPrivat();
Related
I'm programming a password manager app with a MySql database and a spring boot back-end.
My routes on the spring boot back-end work perfectly and I tested them with postman. Most of them also work in my android studio app with the help of retrofit. But the last one that I need is updateAccountById() with a Put request.
This Put route works with postman but won't work in my android studio app and I can't seem to find why.
This is my repository methods in the spring-boot back-end (There is an #Service with the class but stackoverflow doesn't like it) :
public class AccountDao {
#Autowired
private AccountRepository accountRepository;
/** Create new account **/
public Account save(Account account){
return accountRepository.save(account);
}
/** Delete account **/
public void deleteById(int id){
accountRepository.deleteById(id);
}
/** Get all accounts **/
public List<Account> getAllAccounts() {
List<Account> accounts = new ArrayList<>();
Streamable.of(accountRepository.findAll()).get().forEach(accounts::add);
return accounts;
}
/** Get accounts by category **/
public List<Account> getAccountsByCategory(int id){
List<Account> accountsByCategory = new ArrayList<>();
Streamable.of(accountRepository.findAll()).get().filter(account -> account.getCategoryId() == id).forEach(accountsByCategory::add);
return accountsByCategory;
}
/** Get account by id **/
public Account getAccountById(int id){
return accountRepository.findById(id).get();
}
/** Get favorites accounts **/
public List<Account> getFavoriteAccounts(){
List<Account> accounts = new ArrayList<>();
Streamable.of(accountRepository.findAll()).get().filter(Account::getFavorite).forEach(accounts::add);
return accounts;
}
}
Then this is my rest-api routes in my controller (There is an #Restcontroller) :
public class Controller {
/** DAO initialization **/
#Autowired
CategoryDao categoryDao = new CategoryDao();
#Autowired
AccountDao accountDao = new AccountDao();
/** REST routes **/
/** Categories routes **/
/* Get one category by id */
#GetMapping("/category/{id}")
public Category getCategoryById(#PathVariable int id) {
return categoryDao.getCategoryById(id);
}
/* Get all categories route */
#GetMapping("/categories")
public List<Category> getCategories(){
return categoryDao.getAllCategory();
}
/* Create a new category */
#PostMapping("/category/save")
public Category newCategory(#RequestBody Category category){
return categoryDao.save(category);
}
/* Delete a category */
#DeleteMapping("/category/delete/{categoryId}")
public void delCategory(#PathVariable int categoryId){
categoryDao.deleteById(categoryId);
}
/** Accounts routes **/
/* Get accounts by category */
#GetMapping("accounts/{categoryId}")
public List<Account> getCategory(#PathVariable int categoryId){
return accountDao.getAccountsByCategory(categoryId);
}
/* Get one account by ID */
#GetMapping("/account/{accountId}")
public Account getAccount(#PathVariable int accountId){
return accountDao.getAccountById(accountId);
}
#GetMapping("accounts/favorite")
public List<Account> favorites(){
return accountDao.getFavoriteAccounts();
}
/* Create new account */
#PostMapping("/account/save")
public Account newAccount(#RequestBody Account account){
return accountDao.save(account);
}
/* Edit an account */
#PutMapping("/update/{accountId}")
public ResponseEntity<Account> updateAccount(#PathVariable int accountId, #RequestBody Account accountDetails){
Account account = accountDao.getAccountById(accountId);
account.setCategoryId(accountDetails.getCategoryId());
account.setName(accountDetails.getName());
account.setUserName(accountDetails.getUserName());
account.setPassword(accountDetails.getPassword());
account.setUrl(accountDetails.getUrl());
account.setFavorite(accountDetails.getFavorite());
Account updateAccount = accountDao.save(account);
return ResponseEntity.ok().body(updateAccount);
}
/* Delete an Account */
#DeleteMapping("/account/delete/{accountId}")
public void delAccount(#PathVariable int accountId){
accountDao.deleteById(accountId);
}
}
Finally, this is my retrofit routes on Android Studio with the way I use it :
public interface AccountApi {
#GET("/account/{categoryId}")
Call<Account> getAccount(#Path("categoryId") int id);
#GET("/accounts/{categoryId}")
Call<List<Account>> getAccountsByCategory(#Path("categoryId") int id);
#GET("/accounts/favorite")
Call<List<Account>> getFavoriteAccounts();
#POST("/account/save")
Call<Account> saveAccount(#Body Account account);
#PUT("/update/{accountId}")
Call<Account> updateAccount(#Path("accountId") int id, #Body Account account);
#DELETE("/account/delete/{id}")
Call<ResponseBody> deleteAccount(#Path("id") int id);
}
This is in an OnClickListener :
accountApi.getAccount(getArguments().getInt("accountID")).enqueue(new Callback<Account>() {
#Override
public void onResponse(Call<Account> call, Response<Account> response) {
edit_name.setText(response.body().getName());
edit_username.setText(response.body().getUserName());
edit_password.setText(response.body().getPassword());
edit_url.setText(response.body().getUrl());
edit_favorite.setChecked(response.body().getFavorite());
}
#Override
public void onFailure(Call<Account> call, Throwable t) {
}
});
I would like to show my loading animation during all the consecutive calls and then hide it, whatever is the result.
I have a 1 year working expirience in angular 4+, where is simple to concatenate endpoint calls and then do some actions when the calls have ended.
An angular example:
this.showLoadingIndicator()
this.myEndpointService.getA
.pipe(
tap(resultA => this.myEndpointService.getBFromA(resultA)),
switchMap(resultB => this.myEndpointService.getCFromB(resultB)),
tap(resultC => this.myC = resultC),
finally(this.hideLoadingIndicator())
)
.subscribe (
() => this.successDialog('so good so far'),
error => {/*errors*/}
);
and an (limited) example of the EndpointService:
getA(): Observable<any> {
const url = `${this.apiEndpoint}/getA`;
return this.http.get<any>(url);
}
With just few lines of code (I skipped the part about adding headers) I can call multiple endpoint, execute one after another, and finally hide the loadingIndicator no-matter-what.
In android i have a longer code, but with singleton and generics the logic flows nicely.
I have implemented Volley as singleton:
public class VolleyNetworkSingleton {
private static VolleyNetworkSingleton instance;
private static Context ctx;
private RequestQueue requestQueue;
private VolleyNetworkSingleton(Context context) {
ctx = context;
requestQueue = getRequestQueue();
}
/**
* Ensures that the Class is instantiated only once
* and the same instance is used throughout the application.
*
* #return the Class instance.
*/
public static synchronized VolleyNetworkSingleton getInstance(Context context) {
if (instance == null) {
instance = new VolleyNetworkSingleton(context);
}
return instance;
}
/**
* Ensures that the requestQueue is instantiated only once
* and the same instance is used throughout the application.
*
* #return the RequestQueue.
*/
public RequestQueue getRequestQueue() {
if (requestQueue == null) {
// getApplicationContext() is key, it keeps you from leaking the
// Activity or BroadcastReceiver if someone passes one in.
requestQueue = Volley.newRequestQueue(ctx.getApplicationContext());
}
return requestQueue;
}
/**
* #param req the request to add
* #param tag the tag to associate the request
* #param <T> the generic Type used
*/
public <T> void addToRequestQueue(Request<T> req, String tag) {
req.setTag(tag);
getRequestQueue().add(req);
}
/**
* #param tag used to delete the associated Request
*/
public void cancelAllRequests(String tag) {
getRequestQueue().cancelAll(tag);
}
}
Then i customized the VolleyRequest with some features:
- generic body which is automatically parsed as json,
- generic response which is also parsed back to an Object
- added request headers
public class AuthorizedRequest extends Request {
private static final String TAG = "AuthorizedRequest";
private Response.Listener listener;
/**
* Declare a gson variable which will be used to convert the json response
* to POJO
**/
private Gson gson;
private Object body;
/**
* Declare a Class variable. This Class will represent the POJO. Basically
* this variable will hold the instance of the java object which you
* want as response
**/
private Class responseClass;
private Context context;
/**
* Constructor for your custom class
*
* #param method Http method
* #param url url of the request
* #param requestBody body of the request
* #param responseClass Object type of the response
* #param context the context
* #param listener listener to notify success response
* #param errorListener listener to notify error response
*/
public <T> AuthorizedRequest(int method,
String url,
#Nullable T requestBody,
Class responseClass,
Context context,
Response.Listener listener,
Response.ErrorListener errorListener) {
super(method, url, errorListener);
gson = new GsonBuilder().registerTypeAdapter(Date.class, new DateDeserializer()).create();
this.listener = listener;
this.body = requestBody;
this.context = context;
this.responseClass = responseClass;
}
/**
* This method needs to be implemented to parse the raw network response
* and return an appropriate response type.This method will be called
* from a worker thread. The response
* will not be delivered if you return null.
*
* #param response Response payload as byte[],headers and status code
**/
#Override
protected Response parseNetworkResponse(NetworkResponse response) {
try {
// First convert the NetworkResponse into a jsonstring.
String jsonString = new String(
response.data,
HttpHeaderParser.parseCharset(response.headers, "utf-8"));
// Then that json string can be converted into the required java.object<Gson>
return Response.success(
gson.fromJson(jsonString, responseClass),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return Response.error(new ParseError(e));
}
}
/**
* This is called on the main thread with the object you returned in
* parseNetworkResponse(). You should be invoking your callback interface
* from here
**/
#Override
protected void deliverResponse(Object response) {
listener.onResponse(response);
}
/**
* Parse the body of the request
*
* #return the parsed body
*/
#Override
public byte[] getBody() {
String parsedBody = new String();
try {
parsedBody = parseBody(body);
return parsedBody == null ? null : parsedBody.getBytes("utf-8");
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", parsedBody, "utf-8");
return null;
}
}
/**
* Applies the AccessToken logic and if successful, builds the headers
*
* #return the headers
*/
#Override
public Map<String, String> getHeaders() {
try {
if (MyUtils.isRefreshTokenExpired(context)) {
return null;
}
if (MyUtils.isAccessTokenExpired(context)) {
GoToLogin();
return null;
}
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
return headers;
} catch (IOException e) {
Log.e(TAG, e.getMessage() + e.getStackTrace());
String message = context.getResources().getString(R.string.no_internet_connection);
return null;
}
}
/**
* Converts the object to string
*
* #param obj the object to parse
* #param <T> the object's type
* #return the string of the parsed body
*/
private <T> String parseBody(T obj) {
try {
if (obj == null)
return null;
JSONObject jsonBody = new JSONObject(gson.toJson(obj));
return jsonBody.toString();
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
}
Then i just use it like this:
AuthorizedRequest request = new AuthorizedRequest(
Request.Method.GET,
buildUrl(),
null, /*no body needed*/
MyObject.class, /*what i expect to receive*/
getContext(),
new Response.Listener<MyObject >() {
#Override
public void onResponse(MyObject response) {
if (response.getProp1() == null)
showEmptyPropMessage();
else {
myProp1.setText(response.getProp1());
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
// Add the request to the RequestQueue.
VolleyNetworkSingleton.getInstance(getContext()).addToRequestQueue(request, "GET_MY_OBJECT");
Despite the amount of code needed this works great!
But how do I concatenate multiple request to show the loadingIndicator before calling them and then hiding it just once?
Do i have to put each request inside of another (actually, inside Response.Listener())? Because.. yeah, I can do it (one inside another), and hostestly is not that bad.. but then i will have to hide the loadingIndicator every time there is an error.
Moreover, if wanted to create two chain of calls, that differs just by the order of endpoint call, i will have to write the same code twice.
example getA then getB case:
private void getAandThenB() {
AuthorizedRequest reqA = new AuthorizedRequest(Method, url, null, A.class, context, Response.Listener { getB();}, Response.ErrorListener{});
VolleyNetworkSingleton.getInstance(getContext()).addToRequestQueue(request, "GET_A");
}
private void getB() {
AuthorizedRequest reqB = new AuthorizedRequest(Method, url, null, B.class, context, Response.Listener { /*do something*/}, Response.ErrorListener{});
VolleyNetworkSingleton.getInstance(getContext()).addToRequestQueue(request, "GET_B");
}
If in the same class i also want to refresh just A, i have to write another function, lets call it getJustA() where the only difference is the action in the response:
private void getJustA() {
AuthorizedRequest reqA = new AuthorizedRequest(Method, url, null, A.class, context, Response.Listener { refreshA()}, Response.ErrorListener{});
VolleyNetworkSingleton.getInstance(getContext()).addToRequestQueue(request, "GET_A");
}
As you can see, just to express a simple case scenario, this get out of hands very quickly.
I have followed a tutorial on how to setup SNS Push notification but the CreatePlatformEndpointResult object returns null. I need that so that I can retrieve the endpointArn and send that to the backend. Below is my entire setup. And here is the link to the tutorial: http://www.allcode.com/amazon-sns-push-notification-tutorial-android-using-gcm/
First I retrieve a token from GCM by calling
AWSManager.registerAppToGCM(getApplicationContext())
This is from my AWSManager class
public class AWSManager {
private static final String TAG = AWSManager.class.getSimpleName();
private static final String SNS_ACCESS_KEY_ID = "1234567890"; // I have swapped out the real key
private static final String SNS_SECRET_KEY = "1234567890"; // I have swapped out the real key
private static AmazonSNSClient snsClient;
/**
* Method is used to retrieve SNSClient object
*
* #return snsClient object
*/
public static AmazonSNSClient getSNSClient() {
if (FrameworkUtils.checkIfNull(snsClient)) {
snsClient = new AmazonSNSClient(new BasicAWSCredentials(SNS_ACCESS_KEY_ID, SNS_SECRET_KEY));
snsClient.setRegion(Region.getRegion(Regions.US_WEST_1));
}
return snsClient;
}
/**
* Method is used to register app to GCM
*
* #param context
*/
public static void registerAppToGCM(Context context) {
SharedPref sharedPref = new SharedPref(context, Constants.PREF_FILE_NAME);
String gcmToken = sharedPref.getStringPref(Constants.NOTIFICATION_GCM_TOKEN, "");
if (FrameworkUtils.isStringEmpty(gcmToken)) {
new GCMRegisterTask(context).execute();
}
}
}
Here is the class performing the background task
public class GCMRegisterTask extends AsyncTask<String, Void, Boolean> {
private static final String TAG = GCMRegisterTask.class.getSimpleName();
private Context mContext;
/**
* Constructor
*
* #param context
*/
public GCMRegisterTask(Context context) {
super();
mContext = context;
}
#Override
protected Boolean doInBackground(String... params) {
String token;
try {
token = InstanceID.getInstance(mContext).getToken(mContext.getString(R.string.gcm_project_id), GoogleCloudMessaging.INSTANCE_ID_SCOPE);
SharedPref sharedPref = new SharedPref(mContext, Constants.PREF_FILE_NAME);
sharedPref.setPref(Constants.NOTIFICATION_GCM_TOKEN, token);
Logger.i(TAG, "GCM token successfully stored to prefs: " + token);
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
}
Once I have successfully retrieved the GCM token. I use new
AWSCreateEndpointTask(mContext).execute(test, token,
"email#gmail.com")
to begin the process of creating the endpoint ARN. test = "arn:aws:sns:region:us-east-1:app/GCM/AppName"
public class AWSCreateEndpointTask extends AsyncTask<String, Void, CreatePlatformEndpointResult> {
Context mContext;
/**
* Constructor
*
* #param context
*/
public AWSCreateEndpointTask(Context context) {
super();
mContext = context;
}
#Override
protected CreatePlatformEndpointResult doInBackground(String[] params) {
if (params.length < 3) {
return null;
}
String arn = params[0];
String gcmToken = params[1];
String userData = params[2];
try {
CreatePlatformEndpointRequest request = new CreatePlatformEndpointRequest();
request.setCustomUserData(userData);
request.setToken(gcmToken);
request.setPlatformApplicationArn(arn);
return AWSManager.getSNSClient().createPlatformEndpoint(request);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(CreatePlatformEndpointResult result) {
if (!FrameworkUtils.checkIfNull(result)) {
String endpointArn = result.getEndpointArn();
SharedPref sharedPref = new SharedPref(mContext, Constants.PREF_FILE_NAME);
sharedPref.setPref(Constants.NOTIFICATION_ENDPOINT_ARN, endpointArn);
}
}
Inside of onPostExecute, the returned CreatePlatformEndpointResult object is null. What am I missing or doing incorrectly to cause this?
It turns out that the implementation is correct, the arn value was wrong. For others running into this conflict, make sure the information is correct when trying to get the endpointARN. I updated mine to
arn:aws:sns:us-east-1::app/GCM/
This comes from the developer console.
So i deployed an api and imported the sdk into android. I tried to perform a simple GET method. Where I input a userName and it returns to me the user's lastName.
The lambda function (backend function) is called, so i am able to connect to it, but im not able to get the output.
Here is my class:
public class SampleGet extends AppCompatActivity
{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_log_in);
gatewayButton = (Button) findViewById(R.id.cognito_gatewayButton);
gatewayButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
gateWayAsyncTask gateWayAsyncTask = new gateWayAsyncTask();
gateWayAsyncTask.execute();
}
});
}
class gateWayAsyncTask extends AsyncTask<Void, Void, Void>
{
private String userName;
#Override
protected Void doInBackground(Void... params)
{
//gateway
creatingUser = clientFactory.build(MyUserClient.class);
userName = creatingUser.rootGet("SampleUserName").getLastName;
return null;
}
#Override
public void onPostExecute(Void var)
{
Log.d("gateway","gateway succeded!");
if( userName == null)
{
Log.d("gateway","username is null");
}
else if(userName.equals(""))
{
Log.d("gateway","username is empty");
}
else
{
Log.d("gateway",userName);
}
}
}
In the sdk i generated from api gateway here is the client class:
#com.amazonaws.mobileconnectors.apigateway.annotation.Service(endpoint = "https://ow2zhiry2b.execute-api.us-west-2.amazonaws.com/test5")
public interface MyUserClient {
/**
* A generic invoker to invoke any API Gateway endpoint.
* #param request
* #return ApiResponse
*/
com.amazonaws.mobileconnectors.apigateway.ApiResponse execute(com.amazonaws.mobileconnectors.apigateway.ApiRequest request);
/**
*
*
* #param username
* #return AndroidOutput
*/
#com.amazonaws.mobileconnectors.apigateway.annotation.Operation(path = "/", method = "GET")
AndroidOutput rootGet(
#com.amazonaws.mobileconnectors.apigateway.annotation.Parameter(name = "username", location = "query")
String username);
}
Here is the AndroidOuput class which was also generated:
public class AndroidOutput {
#com.google.gson.annotations.SerializedName("items")
private String items = null;
/**
* Gets items
*
* #return items
**/
public String getItems() {
return items;
}
/**
* Sets the value of items.
*
* #param items the new value
*/
public void setItems(String items) {
this.items = items;
}
}
So the log that comes out is username is null and i have no idea why. I have checked the cloudwatch, and indeed my backend lambda function is running. And when i test the api in gateway it ran there. If anyone could please help me thatd be awesome!!
If you're familiar with Retrofit and don't want to switch to AWS sdk, you may want to consider adding AWS Gateway OkHttp Interceptor to your OkHttpClient.
Have you considered using the AWS Gateway for Android?
I used the following POJO to create an App Engine Endpoint.
package com.incident.incidentreporter;
import java.util.Date;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import javax.persistence.Entity;
import javax.persistence.Id;
import com.google.appengine.api.datastore.Blob;
#Entity
public class Incidents {
#Id
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;
#Persistent
private Date incidentdate;
#Persistent
private String incidentdetails;
#Persistent
private double lat;
#Persistent
private double lngtitude;
#Persistent
private String reporter;
#Persistent
private Blob incidentimage;
public Incidents() {
// TODO Auto-generated constructor stub
}
public Incidents(Long id, Date incidentdate, String incidentdetails,
double lat, double lngtitude, String reporter, Blob incidentimage) {
super();
this.id = id;
this.incidentdate = incidentdate;
this.incidentdetails = incidentdetails;
this.lat = lat;
this.lngtitude = lngtitude;
this.reporter = reporter;
this.incidentimage = incidentimage;
}
/**
* #return the incidentdate
*/
public Date getIncidentdate() {
return incidentdate;
}
/**
* #param incidentdate the incidentdate to set
*/
public void setIncidentdate(Date incidentdate) {
this.incidentdate = incidentdate;
}
/**
* #return the incidentdetails
*/
public String getIncidentdetails() {
return incidentdetails;
}
/**
* #param incidentdetails the incidentdetails to set
*/
public void setIncidentdetails(String incidentdetails) {
this.incidentdetails = incidentdetails;
}
/**
* #return the lat
*/
public double getLat() {
return lat;
}
/**
* #param lat the lat to set
*/
public void setLat(double lat) {
this.lat = lat;
}
/**
* #return the lngtitude
*/
public double getLngtitude() {
return lngtitude;
}
/**
* #param lngtitude the lngtitude to set
*/
public void setLngtitude(double lngtitude) {
this.lngtitude = lngtitude;
}
/**
* #return the reporter
*/
public String getReporter() {
return reporter;
}
/**
* #param reporter the reporter to set
*/
public void setReporter(String reporter) {
this.reporter = reporter;
}
/**
* #return the incidentimage
*/
public Blob getIncidentimage() {
return incidentimage;
}
/**
* #param incidentimage the incidentimage to set
*/
public void setIncidentimage(Blob incidentimage) {
this.incidentimage = incidentimage;
}
/**
* #return the id
*/
public Long getId() {
return id;
}
}
The auto generated endpoint code is as below.
package com.incident.incidentreporter;
import com.incident.incidentreporter.EMF;
import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.config.ApiNamespace;
import com.google.api.server.spi.response.CollectionResponse;
import com.google.appengine.api.datastore.Cursor;
import com.google.appengine.datanucleus.query.JPACursorHelper;
import java.util.List;
import javax.annotation.Nullable;
import javax.inject.Named;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityNotFoundException;
import javax.persistence.EntityManager;
import javax.persistence.Query;
#Api(name = "incidentsendpoint", namespace = #ApiNamespace(ownerDomain = "incident.com", ownerName = "incident.com", packagePath = "incidentreporter"))
public class IncidentsEndpoint {
/**
* This method lists all the entities inserted in datastore.
* It uses HTTP GET method and paging support.
*
* #return A CollectionResponse class containing the list of all entities
* persisted and a cursor to the next page.
*/
#SuppressWarnings({ "unchecked", "unused" })
#ApiMethod(name = "listIncidents")
public CollectionResponse<Incidents> listIncidents(
#Nullable #Named("cursor") String cursorString,
#Nullable #Named("limit") Integer limit) {
EntityManager mgr = null;
Cursor cursor = null;
List<Incidents> execute = null;
try {
mgr = getEntityManager();
Query query = mgr.createQuery("select from Incidents as Incidents");
if (cursorString != null && cursorString != "") {
cursor = Cursor.fromWebSafeString(cursorString);
query.setHint(JPACursorHelper.CURSOR_HINT, cursor);
}
if (limit != null) {
query.setFirstResult(0);
query.setMaxResults(limit);
}
execute = (List<Incidents>) query.getResultList();
cursor = JPACursorHelper.getCursor(execute);
if (cursor != null)
cursorString = cursor.toWebSafeString();
// Tight loop for fetching all entities from datastore and accomodate
// for lazy fetch.
for (Incidents obj : execute)
;
} finally {
mgr.close();
}
return CollectionResponse.<Incidents> builder().setItems(execute)
.setNextPageToken(cursorString).build();
}
/**
* This method gets the entity having primary key id. It uses HTTP GET method.
*
* #param id the primary key of the java bean.
* #return The entity with primary key id.
*/
#ApiMethod(name = "getIncidents")
public Incidents getIncidents(#Named("id") Long id) {
EntityManager mgr = getEntityManager();
Incidents incidents = null;
try {
incidents = mgr.find(Incidents.class, id);
} finally {
mgr.close();
}
return incidents;
}
/**
* This inserts a new entity into App Engine datastore. If the entity already
* exists in the datastore, an exception is thrown.
* It uses HTTP POST method.
*
* #param incidents the entity to be inserted.
* #return The inserted entity.
*/
#ApiMethod(name = "insertIncidents")
public Incidents insertIncidents(Incidents incidents) {
EntityManager mgr = getEntityManager();
try {
mgr.persist(incidents);
} finally {
mgr.close();
}
return incidents;
}
/**
* This method is used for updating an existing entity. If the entity does not
* exist in the datastore, an exception is thrown.
* It uses HTTP PUT method.
*
* #param incidents the entity to be updated.
* #return The updated entity.
*/
#ApiMethod(name = "updateIncidents")
public Incidents updateIncidents(Incidents incidents) {
EntityManager mgr = getEntityManager();
try {
if (!containsIncidents(incidents)) {
throw new EntityNotFoundException("Object does not exist");
}
mgr.persist(incidents);
} finally {
mgr.close();
}
return incidents;
}
/**
* This method removes the entity with primary key id.
* It uses HTTP DELETE method.
*
* #param id the primary key of the entity to be deleted.
*/
#ApiMethod(name = "removeIncidents")
public void removeIncidents(#Named("id") Long id) {
EntityManager mgr = getEntityManager();
try {
Incidents incidents = mgr.find(Incidents.class, id);
mgr.remove(incidents);
} finally {
mgr.close();
}
}
private boolean containsIncidents(Incidents incidents) {
EntityManager mgr = getEntityManager();
boolean contains = true;
try {
Incidents item = mgr.find(Incidents.class, incidents.getId());
if (item == null) {
contains = false;
}
} finally {
mgr.close();
}
return contains;
}
private static EntityManager getEntityManager() {
return EMF.get().createEntityManager();
}
}
I successfully generated client endpoint libraries and deployed the app to Google App engine.
I thought the key field will be autogenerated.
The problem i am facing now is that the code that inserts the incident fails if i do not set the id field.
Are there errors in my code which caused this problem?
since this field is of Long datatype and must be unique, is there away of adding code to generate it?
I am using an android client app .
Please advise .
Ronald
This part
Query query = mgr.createQuery("select from Incidents as Incidents");
looks very suspicious for me. It is missing the column list from the select clause and I believe you should review the work-flow of all the logistics working with your columns. This might be enough to fix your problem, however, I believe this is where you should start researching your problem.