How to retrieve data from the Google Datastore? - java

I use java servlets. I wrote a code which has no error,But it returns me an empty list always.
I dint want to update Datastore from the servlet. i just want to read entities. i'll enclose my code tell me where is the problem.
I always get the data store is empty.This is just a test code.Even this dosent seem to work. searched internet for week . All for vain.
public class TestServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
resp.setContentType("text/plain");
resp.getWriter().println("Hello, world");
DatastoreService datastoreService = DatastoreServiceFactory.getDatastoreService();
resp.getWriter().println(datastoreService.getIndexes());
if (datastoreService.getIndexes().isEmpty())
resp.getWriter().println("the data store is empty");
Query query = new Query("IMAGES");
PreparedQuery pq = datastoreService.prepare(query);
for (Entity entity :pq.asIterable())
{
resp.getWriter().println(entity.getKind() );
resp.getWriter().println(entity.getAppId() );
resp.getWriter().println(entity.getKey() );
}
if (!pq.asIterable().iterator().hasNext())
resp.getWriter().println("the data store is empty");
}

I rectified my problem . I forgot to add a namespace. here is a snippet on How to set namespace in GAE DataStore.
// Set the namepace temporarily to "abc"
String oldNamespace = NamespaceManager.get();
NamespaceManager.set("abc");
try {
... perform operation using current namespace ...
} finally {
NamespaceManager.set(oldNamespace);
}

Related

IBM Mobilefirst JAVA adapter giving MFP-Conflict=Concurrency failure while storing user data

I am building a JAVA HTTP Adapter, I am authenticating the user in UserAuthenticationSecurityCheck class using the following method
#Override
protected AuthenticatedUser createUser() {
return new AuthenticatedUser(userId, logonId, this.getName(), attributes);
}
#Override
protected boolean validateCredentials(Map<String, Object> credentials) {
return false;
}
After this control goes to android app then they call the REST API called /updateClientRegistrtion which will update the ClientRegistrationData
#GET
public Response updateClientRegistartion(#Context HttpServletRequest request) {
AuthenticatedUser authUser = securityContext.getAuthenticatedUser();
Map<String, Object> attributes = authUser.getAttributes();
ClientData clientData = securityContext.getClientRegistrationData();
clientData.getProtectedAttributes().put(some parameter);
if (clientData.getClientId() != null) {
securityContext.storeClientRegistrationData(clientData);
}
But this code is giving me error like
Exception Message :
409; headers=[ MFP-Conflict=Concurrency failure]; body={}
Is there any solution to this problem? Can someone please help me with this.
Tutorial followed : http://mobilefirstplatform.ibmcloud.com/tutorials/en/foundation/8.0/authentication-and-security/user-authentication/security-check/
409; headers=[ MFP-Conflict=Concurrency failure]; body={}
results when concurrent requests try to store attributes into the same row or the data in the row being modified by another request before it was updated.
This could be from the request being fired more than once ( in close proximity).Another possibility is that while one request was working on the data in memory, another had already modified and updated it.
The code should still work without the line:
securityContext.storeClientRegistrationData(clientData);
Try that out.
Alternatively, put a try-catch around the
storeClientRegistrationData(clientData)
and retry in the catch block.

Java - How to Retrieve and use a single value from azure mobile services in Android

I am new to azure but i know certain things like how to retrieve and store data to azure , i followed azure official documentation for this purpose.
Link is Here - https://azure.microsoft.com/en-in/documentation/articles/mobile-services-android-get-started-data/
But the problem is, this tutorial is only showing How to retrieve and use Data from azure using Adapters and Lists . I want to know , How can i retrieve a single value from azure mobile services and how to use it in android.
Plzz provide me both backend code (if there is any) and java code for this . THANKS in advance
I got it solved. No need to create a custom API.
Just follow the basics , Here is the code :-
final String[] design = new String[1];
private MobileServiceTable<User> mUser;
mUser = mClient.getTable(User.class);
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
try {
final MobileServiceList<User> result =
mUser.where().field("name").eq(x).execute().get();
for (User item : result) {
// Log.i(TAG, "Read object with ID " + item.id);
desig[0] = item.getDesignation(); //getDesignation() is a function in User class ie- they are getters and setters
Log.v("FINALLY DESIGNATION IS", desig[0]);
}
} catch (Exception exception) {
exception.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
designation.setText(desig[0]);
}
}.execute();
DON'T forget to create a class User for serialization and all. Also you should define the array .
FEEL FREE to write if you got it not working.
EDIT :-
design[0] is an array with size 1.
eq(x) is equal to x where , x variable contains username for which i want designation from database (azure).
You can do this with a custom API. See this link: https://azure.microsoft.com/en-us/documentation/articles/mobile-services-how-to-use-server-scripts/#custom-api
Code looks like this:
exports.post = function(request, response) {
response.send(200, "{ message: 'Hello, world!' }");
}
It's then reachable at https://todolist.azure-mobile.net/api/APIFILENAME.
If you want to access a table you can do something like:
exports.post = function(request, response) {
var userTable = tables.getTable('users');
permissionsTable
.where({ userId: user.userId})
.read({ success: sendUser });
}
function sendUser(results){
if(results.length <= 0) {
res.send(200, {});
} else {
res.send(200, {result: results[0]});
}
}
You can then follow the instructions for using the API on your Android client here: https://azure.microsoft.com/en-us/documentation/articles/mobile-services-android-call-custom-api/
How your app is written will change how this code works/looks, but it looks something like:
ListenableFuture<MarkAllResult> result = mClient.invokeApi( "UsersAPI", MarkAllResult.class );
That invokes the API. You need to write the class and Future to handle the results. The above page explains this in great detail.
The most optimal solution would be to create an api on your server which accepts an ID to return an single object/tablerow.
In your android app, you only have to call:
MobileServiceTable<YourClass> mYourTable;
mClient = new MobileServiceClient(
"https://yoursite.azurewebsites.net/",
mContext);
mYourTable = mClient.getTable(YourClass.class);
YourClass request = mYourTable.lookUp(someId).get();
// request -> https://yoursite.azurewebsites.net/tables/yourclass/someId
YourClass should have the same properties as the object on the server.

Strategy when retrieving user name from session

I have a technical problem and I am not sure about the correct way to solve:
In a web page I am developing, I have to store the current user name from session (the person who is logged in) to "stamp" an action. (For instance, "The user created this file on "). My algorithm retrieves the user name from session but it obviously changes for each user. Therefore, the is always been the one of the user logged in, and not the creator name.
Any hint anyone?
Thanks!
So logically these are the steps you want?
User1 logs in
User1's name gets stored in Http session
User1 creates File42
System stores in database that User1 created File42 on Timestamp257
User1 logs out
User 2 logs in
User2's name gets stored in Http session
User2 views information about File42
System reads from database that User1 created File42 on Timestamp257
System displays information to User2
I think you might be missing the part where the system stores stuff (e.g. in a database).
EDIT: If you don't need persistence you could store shared data in the ServletContext. Note this is not a serious solution but could be used for a quick prototype or demo. Don't even think about doing this in production, it's got issues.
In your servlet do:
private static Map<String, FileData> fileAccess;
private class FileData {
String userName;
Date timeStamp = new Date();;
String fileName;
FileData(String userName, String fileName) {
this.userName = userName;
this.fileName= fileName;
}
}
public void init(ServletConfig config) {
String attributeKey = "fileAccess";
fileAccess = config.getServletContext().getAttribute(attributeKey);
if (fileAccess == null) {
fileAccess = new HashMap<String, FileData>();
config.getServletContext().setAttribute(attributeKey, fileAccess);
}
}
// in this example a POST means a user accesses a file
public void doPost(HttpServletRequest req, HttpServletResponse resp) {
// get the user name from the current session
String userName = req.getSession().getAttribute("userName");
// get the file name from the request (posted from the file access form)
String fileName = req.getParameter("fileName");
// check if we have the necessary data
if (userName == null || fileName == null) {
resp.getWriter().write("Invalid file access request");
resp.getWriter().flush();
return;
}
// create and fill file data wrapper
FileData fileData = new FileData(userName, fileName);
// store the file data in the shared fileAccess map.
// synchronized to block simultaneous acccess from different threads
synchronized (fileAccess) {
// note: any previously stored FileData object gets replaced
fileAccess.put(fileName, fileData);
}
// display the result to the user
display(fileData, resp);
}
// in this example a GET means a user views a file
public void doGet(HttpServletRequest req, HttpServletResponse resp) {
// get the file name parameter from the request (sent as part of the view-file request)
String fileName = req.getParameter("fileName");
// check if we have the necessary data
if (fileName == null) {
resp.getWriter().write("Invalid view file request.");
resp.getWriter().flush();
return;
}
// get the file data from the shared fileAccess map.
// synchronized to block simultaneous acccess from different threads
synchronized (fileAccess) {
FileData fileData = fileAccess.get(fileName);
// display the result to the user
display(fileData, resp);
}
}
private void display(FileData fileData, HttpServletResponse resp) {
resp.getWriter().write("File accessed:");
resp.getWriter().write("User: " + fileData.userName);
resp.getWriter().write("File: " + fileData.fileName);
resp.getWriter().write("Timestamp: " + fileData.timeStamp);
resp.getWriter().flush();
}

Set data into ActionResponse Portlet GateIn

I am working on portlet for GateIn 3.6. Currently i have created a page that list the records in table. When user click on any row then it takes to description page.
Right now when user click on row it loads the details page but values are not available. What i am doing details are here..
#RenderMode(name = "view")
public void display(RenderRequest request, RenderResponse response) throws PortletException, IOException, NamingException {
RecordsDAO recordsDAO = new RecordsDAOImpl();
// Records listing available on listing page
request.setAttribute("recordsList", recordsDAO.getAllRecords());
// tried to load record detail page when user click one row
if(actionJsp == null || actionJsp.equals("")){
getPortletContext().getRequestDispatcher("/jsp/ListRecords.jsp").
include(request, response);
} else {
getPortletContext().getRequestDispatcher("/jsp/DetailsBoxRecord.jsp").
include(request, response);
}
actionJsp = "";
}
and the process action is
#ProcessAction(name = "details")
public void details(ActionRequest request, ActionResponse response) throws PortletException, IOException {
RecordsDAO recordsDAO = new RecordsDAOImpl();
int id = Integer.parseInt(request.getParameter("id"));
RecordsForm recordsForm = recordsDAO.getRecord(id);
// way 1 set request attribute
request.setAttribute("details", recordsForm);
// way 2 set response attribute -- display error that cannot set Form type values
response.setRenderParameter("details", recordsForm);
actionJsp = "values";
}
Option1:
I have tried to set RecordsForm type values in request.setAttribute, its done but the values in request are not available in jsp page.
Option2:
Using response.setRenderParameter I am not able to set RecordsForm type values in response.setRenderParameter to access these values in jsp page.
Can anyone please guide me which one is correct way in my case and how these values will be available in jsp page so i can load detail page.
This line of code
response.setRenderParameter("details", recordsForm);
will only pass the recordsForm object to the doView method as parameter. Your JSP is likely trying to use attributes on the RenderRequest. This means in your doView you will need to do something like the following
RecordsForm recordsForm = request.getParameter("details");
request.setAttribute("details", recordsForm);
There is also the option to use the portlet container runtime option javax.portlet.actionScopedRequestAttributes. You set this in your portlet.xml and it should take attributes you set in an action method and provide them as attributes in your render method, eliminating the need to move your objects from the parameters map to the attributes map yourself.
Unrelated note: It looks like you're using actionJsp as an object variable in your portlet. That's not recommended because portlets should be coded to be thread safe. Object variables are shared between users and threads, so saving user specific state data in them will cause errors when you get multiple users.
After adding actionScopedRequestAttributes in portlet.xml i am able to set the values in request and these values are available in jsp pages.
<container-runtime-option>
<name>javax.portlet.actionScopedRequestAttributes</name>
<value>true</value>
</container-runtime-option>
and process action is some thing like that
#ProcessAction(name = "details")
public void details(ActionRequest request, ActionResponse response) throws PortletException, IOException {
RecordsDAO recordsDAO = new RecordsDAOImpl();
int id = Integer.parseInt(request.getParameter("id"));
RecordsForm recordsForm = recordsDAO.getRecord(id);
request.setAttribute("details", recordsForm);
}

How to browse local Java App Engine datastore?

It seems there is no equivalent of Python App Engine's _ah/admin for the Java implementation of Google App Engine.
Is there a manual way I can browse the datastore? Where are the files to be found on my machine? (I am using the App Engine plugin with Eclipse on OS X).
http://googleappengine.blogspot.com/2009/07/google-app-engine-for-java-sdk-122.html: "At long last, the dev appserver has a data viewer. Start your app locally and point your browser to http://localhost:8888/_ah/admin http://localhost:8000/datastore* to check it out."
* as of 1.7.7
There's currently no datastore viewer for the Java SDK - one should be coming in the next SDK release. In the meantime, your best bet is to write your own admin interface with datastore viewing code - or wait for the next SDK release.
Java App Engine now has a local datastore viewer, accessible at http://localhost:8080/_ah/admin.
I have local datastore on my Windows+Eclipse environment on \war\WEB-INF\appengine-generated\local_db.bin
As far as I understood it uses internal format named "protocol buffers". I don't have external tools to present the file in human-readable format.
I'm using simple "viewer" code like this:
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException
{
resp.setContentType("text/plain");
final DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
final Query query = new Query("Table/Entity Name");
//query.addSort(Entity.KEY_RESERVED_PROPERTY, Query.SortDirection.DESCENDING);
for (final Entity entity : datastore.prepare(query).asIterable()) {
resp.getWriter().println(entity.getKey().toString());
final Map<String, Object> properties = entity.getProperties();
final String[] propertyNames = properties.keySet().toArray(
new String[properties.size()]);
for(final String propertyName : propertyNames) {
resp.getWriter().println("-> " + propertyName + ": " + entity.getProperty(propertyName));
}
}
}
In the newest versions of the SDK (1.7.6+) the admin part of the dev server comes with it changed its location
Analyzing the server output logs we can see that it is accessible at:
http://localhost:8000
And the Datastore viewer:
http://localhost:8000/datastore
Looks pretty neat - according to google's new design guidlines.
Because Google App Engines Datastore viewer does not support displaying collections of referenced entities, I modified Paul's version to display all descendant entities:
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String entityParam = req.getParameter("e");
resp.setContentType("text/plain");
final DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
// Original query
final Query queryOrig = new Query(entityParam);
queryOrig.addSort(Entity.KEY_RESERVED_PROPERTY, Query.SortDirection.ASCENDING);
for (final Entity entityOrig : datastore.prepare(queryOrig).asIterable()) {
// Query for this entity and all its descendant entities and collections
final Query query = new Query();
query.setAncestor(entityOrig.getKey());
query.addSort(Entity.KEY_RESERVED_PROPERTY, Query.SortDirection.ASCENDING);
for (final Entity entity : datastore.prepare(query).asIterable()) {
resp.getWriter().println(entity.getKey().toString());
// Print properties
final Map<String, Object> properties = entity.getProperties();
final String[] propertyNames = properties.keySet().toArray(new String[properties.size()]);
for(final String propertyName : propertyNames) {
resp.getWriter().println("-> " + propertyName + ": " + entity.getProperty(propertyName));
}
}
}
}
It should be noted that nothing is displayed for empty collections/referenced entities.
Open the \war\WEB-INF\appengine-generated\local_db.bin file with a text editor, like Notepad++.
The data is scrambled but at least you can read it and you can copy to extract it.
For me the fix was to do the login using below gcloud command
gcloud auth application-default login

Categories