In my program, I am trying to get the last modified date for some items in my box folders, but I am unable to access that information.
According to the documentation for the box API and the javadoc for the java library, any of the following methods of BoxTypedObject should return the information I want:
getModifiedAt() should return a String in ISO 8601 format for the date.
getModifiedDate() should return a Date object for the date.
getValue("modified_at") should also return a String in ISO 8601 format for the date.
getExtraData("modified_at") is also a possible way, although I am not as sure of this one.
However, none of those methods has worked for me; they all just returh null.
The (vastly simplified) code that I am using to retrieve the dates is as follows, with one of the above methods substituted for the comment block:
private static void printAll(BoxFolder boxFolder){
for(BoxTypedObject file : boxFolder.getItemCollection().getEntries())
System.out.printf("[\"%1$s\" %2$s]%n",
file.getValue("name"), file./*[???]*/);
}
The other fields all return the correct values, only when I try to get the date does it fail on me.
How do I retrieve the modified date for the BoxTypedObjects?
EDIT: I have figured out one way to get it, but it is somewhat slow.
client.getFilesManager().getFile(file.getId(), null).getModifiedAt()
retrieves the date. I am still interested if there is a better way to do it, though.
Additional information (may or may not be relevant to the problem):
The authentication of the box client is handled by the following class:
import java.awt.Desktop;
import java.io.*;
import java.net.*;
import com.box.boxjavalibv2.BoxClient;
import com.box.boxjavalibv2.dao.BoxOAuthToken;
import com.box.boxjavalibv2.exceptions.*;
import com.box.boxjavalibv2.requests.requestobjects.BoxOAuthRequestObject;
import com.box.restclientv2.exceptions.BoxRestException;
/**
* This class handles the storage and use of authentication keys, to
* simplify the process of obtaining n authenticated client. This class
* will store refresh keys in a file, so that it can authenticate a client
* without needing for user intervention.
* <p>
* Copyright 2013 Mallick Mechanical, Inc.
*
* #author Anson Mansfield
*/
public class Authenticator {
/**
* Constructs an {#code Authenticator} for use obtaining
* authenticated {#Code BoxClient}s
*
* #param key The OAuth client id and application key.
* #param secret The OAuth client secret.
* #param authFile The file to be used for storing authentications
* for later use.
*/
public Authenticator(String key, String secret, File authFile){
this.key = key;
this.secret = secret;
this.authFile = authFile;
}
/**
* Constructs a new {#Code BoxClient} object, authenticates it,
* and returns it.
*/
public BoxClient getAuthenticatedClient(){
BoxClient client = new BoxClient(key,secret);
client.authenticate(getToken(client));
return client;
}
public final String host = "http://localhost";
public final int port = 4000;
public final String key, secret;
public final File authFile;
public final String url = "https://www.box.com/api/oauth2/authorize?response_type=code&client_id=";
/**
* Obtains a token that can be used to authenticate the box client,
* and stores its refresh value in a file, so it can be used later.
* #param client The client to obtain a token for.
* #return A token that can be used to authenticate the client, or
* {#code null} if one could not be obtained.
*/
private BoxOAuthToken getToken(BoxClient client){
BoxOAuthToken token = null;
try{
if((token = getOldToken(client)) != null) return token;
if((token = getNewToken(client)) != null) return token;
return token;
}finally{
writeNewToken(token);
}
}
/**
* Attempts to write a token's refresh token to a file.
* #param token The token whose refresh value is to be written.
*/
private void writeNewToken(BoxOAuthToken token) {
if(token != null)
try(BufferedWriter out = new BufferedWriter(new FileWriter(authFile))){
out.write(token.getRefreshToken());
}catch(IOException ex){
System.out.println("couldn't update new token");
}
}
/**
* Reads the last session's refresh token from a file and attempts
* to get a new authentication token with it.
* #param client The client for which the authentication token is for.
* #return The token obtained from the refresh, or {#code null} if one
* could not be obtained.
*/
private BoxOAuthToken getOldToken(BoxClient client) {
System.out.println("attempting to use old token");
BoxOAuthToken token = null;
try(BufferedReader in = new BufferedReader(new FileReader(authFile))){
token = client.getOAuthManager().refreshOAuth(
BoxOAuthRequestObject.refreshOAuthRequestObject(
in.readLine(), key, secret
));
System.out.println("refreshed old token");
}catch(IOException ex){
System.out.println("couldn't read old token");
} catch(BoxRestException | BoxServerException | AuthFatalFailureException ex){
System.out.println("couldn't refresh old token");
}
return token;
}
/**
* Connects to the OAuth server and gets a new authentication token.
* #param client The client to get a token for.
* #return The new token obtained from the server, or {#code null} if one could not be obtained.
*/
private BoxOAuthToken getNewToken(BoxClient client) {
System.out.println("attempting to get new token");
BoxOAuthToken token = null;
try {
Desktop.getDesktop().browse(java.net.URI.create(url + key));
token = client.getOAuthManager().createOAuth(
BoxOAuthRequestObject.createOAuthRequestObject(getCode(), key, secret, host + port)
);
} catch (BoxRestException | BoxServerException | AuthFatalFailureException | IOException ex) {
ex.printStackTrace();
return null;
}
return token;
}
/**
* This listens on the configured port for the code included in the callback.
* It also deploys a script on the receiving socket to close the browser tab navigating to it.
* #return The authentication code to generate a token with.
*/
private String getCode(){
try (ServerSocket serverSocket = new ServerSocket(port);
Socket socket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream());){
out.println("<script type=\"text/javascript\">");
out.println( "window.open('', '_self', '');");
out.println( "window.close();");
out.println("</script>"); //Close the tab
while (true){
String code = "";
code = in.readLine ();
System.out.println(code);
String match = "code";
int loc = code.indexOf(match);
if( loc >0 ) {
int httpstr = code.indexOf("HTTP")-1;
code = code.substring(code.indexOf(match), httpstr);
String parts[] = code.split("=");
code=parts[1];
return code;
} else {
// It doesn't have a code
}
}
} catch (IOException | NullPointerException e) {
return "";
}
}
}
The actual class that will be getting the modified field (not yet finished, though):
import java.io.File;
import java.util.Scanner;
import com.box.boxjavalibv2.BoxClient;
import com.box.boxjavalibv2.dao.BoxFolder;
import com.box.boxjavalibv2.dao.BoxTypedObject;
/**
* Copyright 2013 Mallick Mechanical, Inc.
*
* #author Anson Mansfield
*/
public class BoxStuff {
static BoxClient client;
public void main(String ... args) throws Exception {
client = new Authenticator(args[0], args[1], new File(args[2]))
.getAuthenticatedClient();
userSelectFolder("Select the project folder");
}
private static BoxFolder userSelectFolder(String prompt) throws Exception{
Scanner kbd;
if(System.console()!=null)
kbd = new Scanner(System.console().reader());
else
kbd = new Scanner(System.in);
String line = "";
System.out.println();
System.out.println(prompt);
System.out.println("(leave prompt blank to select folder)");
BoxFolder current = client.getFoldersManager().getFolder("0", null);
printAll(current);
System.out.print("select>");
while(!(line = kbd.nextLine()).isEmpty()){
BoxFolder next = select(current, Integer.parseInt(line));
if(next != null) current = next;
printAll(current);
System.out.print("select>");
}
return current;
}
private static void printAll(BoxFolder boxFolder){
int idx=0;
System.out.println(" 0:[parent folder]");
for(BoxTypedObject file : boxFolder
.getItemCollection()
.getEntries()){
if(file.getType().equals("folder")){
System.out.printf("%1$3d:[%2$-32s %3$-6s %4$-9s]%n",
++idx, format((String) file.getValue("name"),30), file.getType(), file.getId());
} else {
System.out.printf(" [%1$-32s %2$-6s %3$-9s Edit:%4$s]%n",
format((String) file.getValue("name"),32), file.getType(), file.getId(), file.getExtraData("modified_at"));
}
}
}
private static String format(CharSequence source, int length){
StringBuilder b = new StringBuilder(length);
b.append('"');
if(source.length() > 30)
b.append(source.subSequence(0, 29)).append('~');
else
b.append(String.format("%1$-30s",source));
b.append('"');
return b.toString();
}
private static BoxFolder select(BoxFolder boxFolder, int i) throws Exception{
int idx=0;
for(BoxTypedObject file : boxFolder.getItemCollection().getEntries()){
if(file.getType().equals("folder") && ++idx == i){
return client.getFoldersManager().getFolder(file.getId(), null);
}
}
if(idx==0){
if(boxFolder.getParent() == null)
return client.getFoldersManager().getFolder("0", null);
else
return client.getFoldersManager().getFolder(boxFolder.getParent().getId(), null);
}else{
System.out.println("Selection is out of range!");
return boxFolder;
}
}
}
If anyone else wants to use these classes for something, just ask me. It is probably OK (they are a mechanical contractor, not a software company), I just need to clear it with my boss (This code does still belong to the company).
This is actually a little tricky. The api call to get folder items by default only return children items with some default fields, they don't include fields like modified_at. However if you supply extra fields parameters you should be able to get them.
Here is what you can do when using the getFolderItems method(this is also in the readme in github):
BoxFolderRequestObject requestObj =
BoxFolderRequestObject.getFolderItemsRequestObject(30, 20)
.addField(BoxFolder.FIELD_NAME)
.addField(BoxFolder.FIELD_MODIFIED_AT);
BoxCollection collection =
boxClient.getFoldersManager().getFolderItems(folderId, requestObj);
There is another tricky thing here though, after you supply these fields, the result children items will only contain the supplied fields(plus some basic fields), so make sure you add all the fields you want.
Here is one way I figured out to get it (that actually works):
client.getFilesManager().getFile(file.getId(), null).getModifiedAt()
This, however, is somewhat slow, so I would greatly appreciate it if someone else knows a faster solution.
Related
I am updating an existing working RCP 3 app from
Kepler to Mars. It was written by another guy so having to learn a lot about RCP as I go.
What worked in Kepler was this:
public class ShowSelectViewDialogHandler extends DialogHandler {
/**
* The name of the parameter providing the view identifier.
*/
private static final String VIEW_ID_COMMAND_PARAMETER_NAME = "org.eclipse.ui.views.showView.viewId"; //$NON-NLS-1$
private static final String MAKE_FAST_COMMAND_PARAMETER_NAME = "org.eclipse.ui.views.showView.makeFast"; //$NON-NLS-1$
private final IHandler handler;
/**
* Creates a new ShowViewHandler that will open the view in its default location.
*/
public ShowSelectViewDialogHandler (final IHandler handler) {
this.handler = handler;
}
#Override
public final Object execute(final ExecutionEvent event) throws ExecutionException {
Object result = null;
IWorkbenchWindow window = EDMUIApplication.instance().getWorkbenchAdvisor().getWorkbenchWindowAdvisor().getWindow();
Map<String, String> parameters = event.getParameters();
String viewId = parameters.get(ShowSelectViewDialogHandler.VIEW_ID_COMMAND_PARAMETER_NAME);
String makeFast = parameters.get(ShowSelectViewDialogHandler.MAKE_FAST_COMMAND_PARAMETER_NAME);
if (viewId == null) {
ShowViewDialog dialog = new ShowViewDialog(window, new EDMUIViewRegistry(EDMUIConstants.CATEGORY_IDS));
if (dialog.open() == Window.OK) {
for (IViewDescriptor viewDescriptor : dialog.getSelection()) {
result = this.openView(window, viewDescriptor.getId(), makeFast);
}
}
} else {
result = this.openView(window, viewId, makeFast);
}
return result;
}
/**
* Opens the view with the given ID.
*
* #param window - workbench window of the view.
* #param viewId - id of the view to open.
* #param makeFast - command parameter.
* #return result of the handler execution.
* #throws ExecutionException - if default handler execution fails.
*/
private Object openView(final IWorkbenchWindow window, final String viewId, final String makeFast) throws ExecutionException {
Object result = null;
try {
Parameterization[] parameterization = this.createParameterization(viewId, makeFast, IWorkbenchCommandConstants.VIEWS_SHOW_VIEW);
result = this.executeDefaultHandler(this.handler, window, parameterization, IWorkbenchCommandConstants.VIEWS_SHOW_VIEW);
} catch (NotDefinedException ex) {
throw new ExecutionException(ex.getMessage(), ex);
}
return result;
}
/**
* Creates parameterization for the command.
*
* #param viewId - view id parameter value.
* #param makeFast - make fast parameter value.
* #param commandId - id of the command.
* #return created parameterization.
* #throws NotDefinedException - if there is no such parameter.
*/
private Parameterization[] createParameterization(final String viewId, final String makeFast, final String commandId) throws NotDefinedException {
ICommandService commandService = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class);
Command command = commandService.getCommand(IWorkbenchCommandConstants.VIEWS_SHOW_VIEW);
IParameter viewIdParameter = command.getParameter(ShowSelectViewDialogHandler.VIEW_ID_COMMAND_PARAMETER_NAME);
IParameter makeFastParameter = command.getParameter(ShowSelectViewDialogHandler.MAKE_FAST_COMMAND_PARAMETER_NAME);
return new Parameterization[] { new Parameterization(viewIdParameter, viewId), new Parameterization(makeFastParameter, makeFast) };
}
But now ShowViewDialog signature has changed. Also the original author made the statement that his approach was based on ShowViewHandler and there must be a better more standard way of achieving the same affect, i.e. controlling the display of our reduced set of views.
Any ideas on how to achieve this? There might be a tutorial somewhere, I found the Vogella one, but it is fairly general.
ShowViewDialog is an internal dialog so it should not have been used in the first place. As you have found internal dialogs can be changed without warning.
It looks like your code is using your own implementation of IViewRegistry. To stick to using only official APIs you would have to write your own version of the show view dialog. This is a fairly simple dialog using FilteredTree and the IViewRegistry getCategories and getViews methods.
There isn't a more standard way of doing this.
In my front end Javascript code, I call Twilio.Device.connect(), and it is not firing a request to my Voice Request URL. I am not sure what is going on here. I ensure that I setup my capability token before hand, and there are no errors, but it still doesn't work. Here is front end JS code.
Twilio.Device.setup(resp.token);
Twilio.Device.connect({autoDial: true});
// respond to "connect" event
Twilio.Device.connect(function (conn) {
alert("Got here!");
}
Also here is my code to generate the token.
public static void getToken()
{
TwilioCapability t = new TwilioCapability(ACCOUNT_SID, AUTH_TOKEN);
t.allowClientOutgoing(APP_SID);
t.allowClientIncoming("test");
try {
throw new OKResponse(ImmutableMap.of("token", t.generateToken(3600)));
} catch (DomainException e) {
Logger.error(e, "Error generating twilio token: %s", e.getMessage());
}
}
I had the same problem,
You need to call the function generateToken() after calling allowClientOutgoing() and allowClientIncoming() so that the object created by Services_Twilio_Capability() has the app link.
This works:
$objToken = new Services_Twilio_Capability($accountSid, $authToken);
$objToken->allowClientOutgoing('APXXXXXXXXXX');
$objToken->allowClientIncoming($_REQUEST['name']);
$strToken = $objToken->generateToken();
This does not:
$objToken = new Services_Twilio_Capability($accountSid, $authToken);
$strToken = $objToken->generateToken();
$objToken->allowClientOutgoing('APXXXXXXXXXX');
$objToken->allowClientIncoming($_REQUEST['name']);
Also, it will not throw an error but your js will always show as "disconnected"
UPDATE
Here is an edit of my backend:
/**
* Create an instance of Services_Twilio_Capability();
*
* #return object
*/
private function instantiateCapability(){
if(is_null($this->objCapability))
$this->objCapability = new \Services_Twilio_Capability(TWILIO_ID, TWILIO_KEY);
return $this->objCapability;
}
/**
* Generate a token
*
* #link http://twilio-php.readthedocs.org/en/latest/usage/token-generation.html
* #param bool $boolOutgoing Allow outgoing connections
* #param bool $boolIncoming Allow incoming connections
* #return string
*/
public function generateToken($boolOutgoing = true, $boolIncoming = true){
$objCapability = $this->instantiateCapability();
if($boolOutgoing) $objCapability->allowClientOutgoing(TWILIO_SID]);
if($boolIncoming) $objCapability >allowClientIncoming($_SESSION[$GLOBALS['APP_NAME'] . 'ID']);
$strToken = $objCapability->generateToken(TOKEN_DURATION);
return json_encode(array('status' => 1, 'token' => $strToken));
}
And here is the frontend (AJAX response callback):
function(result){
if(result.status == 1) {
//Load the twilio object
Twilio.Device.setup(result.token);
}
}
My program appears to work to my liking. However, when I compile it I get this message:
Note: Program.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
What can I do to identify the unsafe operations with -Xlint, or what in program is causing this message? I'm thinking it has something to do with my Node class..?
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import javax.swing.JOptionPane;
/**
* An application that reads from a file, enters/deletes in queue and writes output to the file
*/
public class Program {
/**
* Driver code to test class
*
* #param arguments
* Commandline arguments. 1st argument is input file and 2nd argument is output file
* #throws IOException
*/
public static void main(String[] arguments) throws IOException {
//Queue Object
MyQueue<String> queue= (new MyQueue<String>());
String name;
//reading file
read(queue,arguments[0]);
String[] array = { "Offer Person", "Poll Person", "Peek person","Display Queue", "Exit Program"};
int choice = 0;
// display loop
while (choice != array.length-1) {
choice = JOptionPane.showOptionDialog(null, // put in center of screen
"Press a Button", // message to user
"Queue(Line) of People", // title of window
JOptionPane.YES_NO_CANCEL_OPTION, // type of option
JOptionPane.QUESTION_MESSAGE, // type of message
null, // icon
array, // array of strings
array[array.length - 1]); // default choice (last one)
if(choice==0)
{
//inserting the new name in queue
name=JOptionPane.showInputDialog(null,"Enter Person's name","Input");
queue.offer(name);
}
else if(choice==1){
//Display and remove the name which is at front of line
JOptionPane.showMessageDialog(null, queue.poll() + " is next in line");
}
else if(choice==2){
//Display name which is at front of line
JOptionPane.showMessageDialog(null, queue.peek() + " is front of the line");
}
else if(choice==3){
//Dispay all the list
JOptionPane.showMessageDialog(null, queue.toString());
}
//JOptionPane.showMessageDialog(null, "Your pressed button #" + choice);
}
//calling writing function
write(queue, arguments[1]);
}// end of main()
/**
* Reads a file
* #param queue
* #param file_name name of file
*/
public static void read(QueueInterface<String> queue, String file_name) throws IOException{
try
{
String name;
//creating a buffer reader to read
BufferedReader br= new BufferedReader(new FileReader(file_name));
while((name=br.readLine()) != null){
//putting in the queue
queue.offer(name);
}
//closing buffer reader
br.close();
}
catch(Exception ex)
{
System.err.println(ex.getMessage());
}
}
/**
* Writes the contents of LinkedQueue to the output file at the ned of program
* #param queue QueueInterface methods
* #param file_name name of file
*/
public static void write(QueueInterface<String> queue, String file_name) throws IOException{
try
{
String name;
//creating a buffer writer to write
BufferedWriter bw= new BufferedWriter(new FileWriter(file_name));
while((name=queue.poll()) != null){
//writin in file
bw.write(name);
bw.newLine();
}
//closing buffer
bw.close();
}
catch(Exception ex)
{
System.err.println(ex.getMessage());
}
}
}// end of class
/**
* Interface to be implemented by LinkedQueue
*/
interface QueueInterface<String>
{
public boolean empty();
public boolean offer(String element);
public String poll();
public String peek();
}
class Node<String>
{
private String data;
private Node nextNode;
public Node(String dataObject, Node nextNodeObject)
{
this.data=dataObject;
this.nextNode=nextNodeObject;
}
/**
* Gets the next node
* #return next node
*/
public Node getNext()
{
return nextNode;
}
/**
* Sets the next node of the current node
* #param nextNodeObject next node to be set as next to the current node
*/
public void setNext(Node nextNodeObject)
{
nextNode=nextNodeObject;
}
/**
* Sets data of the current node
* #param dataObject data to be inserted in new node
*/
public void setData(String dataObject)
{
this.data=dataObject;
}
/**
* Gets data of the current node
* #return data of the node
*/
public String getData()
{
return this.data;
}
}
class LinkedQueue implements QueueInterface<String>
{
protected Node<String> lastNode=null;
LinkedQueue() {
}
/**
* Checks if the queue is empty
* #return true if empty, false if not empty
*/
public boolean empty() {
if(lastNode==null)
{
return true;
}
else
return false;
}
/**
* Inserts new node in the queue
* #param element data to be inserted in new node
* #return true on success
*/
public boolean offer(String element)
{
Node<String> newLastNode = new Node<String>(element,null);
//If the LinkedQueue is empty, add the node to the last and point next to itself
if(empty())
{
newLastNode.setNext(newLastNode);
}
else
{
// Adding to the front of queue and updating next of the last node
newLastNode.setNext(lastNode.getNext());
lastNode.setNext(newLastNode);
}
lastNode=newLastNode;
return true;
}
/**
* Removes the first node and returns it
* #return data at first node
*/
public String poll()
{
// If queue is empty then return null
if(empty())
return null;
else
{
Node<String> frontNode = lastNode.getNext();
//Check if there will be no node left after polling this one
if (frontNode == lastNode)
{
lastNode = null;
}
else //Remove the first node and update next of the last node
{
lastNode.setNext(frontNode.getNext());
}
return frontNode.getData();
}
}
/**
* Returns data of the first node without removing it from the queue
* #return data at first node
*/
public String peek()
{
if (empty())
{
return null;
}
else
{
Node<String> frontNode = lastNode.getNext();
return frontNode.getData();
}
}
}
class MyQueue<String> extends LinkedQueue{
/**
* Constructor
*
*/
public MyQueue()
{
super();
}
/**
* Returns a string representation of the object
*
* #return a name on different lines
*/
public java.lang.String toString()
{
// create a variable to return
java.lang.String toReturn = "";
// Traversing the list
Node<String> frontNode = lastNode.getNext();
if(empty()) //If queue is empty
return "";
else if(frontNode==lastNode) //If only one elemtn
{
return frontNode.getData().toString();
}
else //More than one element in the queue
{
while(frontNode != lastNode)
{
toReturn=toReturn+frontNode.getData()+"\n";
frontNode=frontNode.getNext();
}
toReturn= toReturn+frontNode.getData()+"\n"; //Appending data of last node because it will be missed in the loop
}
return toReturn;
}
}
If you're compiling on the command line (i.e. javac Program.java), you just have to add the -Xlint:unchecked parameter to have it print out the warnings for you:
javac Program.java -Xlint:unchecked
That should point out the problem spots to you. But, as #DavidWallace mentioned in a comment, you should consider revising your use of generics to be a bit more clear -- that might reveal your issue to you even without using the -Xlint parameter.
If your classes should really only deal with Strings, then you don't need to include a type parameter at all (right now, in your code, <String> is a type parameter, representing the type you pass in when you use the class -- it doesn't signify that it has to be java.lang.String -- that's why #DavidWallace suggested you use T instead). Here's a good tutorial if you want to brush up on how to use Generics.
Assuming that using "String" as the type parameter is not what causes the actual message (or even if it does), with a quick glance I see:
Node<String> frontNode = lastNode.getNext();
but getNext() returns Node instead of Node<String> (should be Node<T> once you fix the type parameter name).
In jGRASP you can add flags for various commands using "Settings" > "Compiler Settings" > "Workspace" (or "Project..." or "File"). Just add "-Xlint" for "Flags or Args" for the "Compile" command for the Java language.
in jGrasp, the option is under the Settings menu item. Go to Settings-> File/Workspace/Project (pick whichever is applicable to you), and then on the Compiler tag, pick the Flags/Args tab, and then click the box next to Compile and enter -Xlint:unchecked into the text box. Click apply, and on your next build, you will get the messages on what was unchecked.
As others have pointed out, this warning is raised because you are using a raw form of a generic class rather than providing a type parameter to it. -Xlint:unchecked will show you where in your code you did that.
In the build.gradle add
allprojects {
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
}
}
}
I'm using Facebook4j to get status with a keyword
facebook4j.conf.ConfigurationBuilder fac = new facebook4j.conf.ConfigurationBuilder();
fac.setDebugEnabled(true)
.setOAuthAppId("******")
.setOAuthAppSecret("********")
.setOAuthPermissions("email,publish_stream,...");
FacebookFactory ff = new FacebookFactory(fac.build());
facebook = ff.getInstance();
new Thread(new Runnable() {
#Override
public void run() {
try {
search();
}
catch (Exception e) {
// TODO: handle exception
System.out.println(e +" ERROOOOOOR");
}}}).start();
}
//search
public void search() throws Exception {
ResponseList<JSONObject> results = facebook.search("%23morocco");
System.out.println(results);
for (JSONObject result : results) {
System.out.println(result);
}
results = facebook.search("orange", new Reading().until("yesterday"));
System.out.println(results);
for (JSONObject result : results) {
System.out.println(result);
}
}
I replaced * with facebook api key
I have a exception probleme , the error is :
java.lang.IllegalStateException: No Token available. ERROOOOOOR
This is how you could use facebook4j without external configuration files. The code below provides a minimal example. Here is my simple demo:
import facebook4j.Facebook;
import facebook4j.FacebookException;
import facebook4j.FacebookFactory;
import facebook4j.auth.AccessToken;
public class Facebook4JMinimalExample {
/**
* A simple Facebook4J client.
*
*
* #param args
* #throws FacebookException
*/
public static void main(String[] args) throws FacebookException {
// Generate facebook instance.
Facebook facebook = new FacebookFactory().getInstance();
// Use default values for oauth app id.
facebook.setOAuthAppId("", "");
// Get an access token from:
// https://developers.facebook.com/tools/explorer
// Copy and paste it below.
String accessTokenString = "PASTE_YOUR_ACCESS_TOKEN_STRING_HERE";
AccessToken at = new AccessToken(accessTokenString);
// Set access token.
facebook.setOAuthAccessToken(at);
// We're done.
// Write some stuff to your wall.
facebook.postStatusMessage("Wow, it works...");
}
}
Note that it is important to FIRST make a call to "facebook.setOAuthAppId(..)" and THEN set the access token. Otherwise you'll get an IllegalStateException saying "OAuth app id/secret combination not supplied".
In this case, I've just used a default value for OAuthAppId.
You forgot to set the access token with fac.setOAuthAccessToken("*****"). From the docs (emphasis mine):
All Graph API search queries require an access token passed in with the access_token=<token> parameter. The type of access token you need depends on the type of search you're executing.
Searches across page and place objects requires an app access token.
All other endpoints require a user access token.
You can generate one for yourself here, but remember that these access tokens have an expiration time.
I'm doing below procedure for LinkedIn login but unfortunately while loading the LinkedIn for login window of "Grant Yokeapp access to your LinkedIn Account"
It's not showing anything and fires error.
I'm using version of LWuit-1.5 in Eclipse pulsar with S60 SDk 5th installed.
public class Login {
Form form = new Form();
String authorizeUrl = "";
public Form Login() {
Display.init(this);
HttpRequestHandler handler = new HttpRequestHandler();
HTMLComponent htmlC = new HTMLComponent(handler);
user = new LinkedInUser(Const.consumerKey, Const.consumerSecret);
user.fetchNewRequestToken();
if (user.requestToken != null) {
authorizeUrl = "https://www.linkedin.com/uas/oauth/authorize?oauth_token="
+ user.requestToken.getToken();
htmlC.setPage(authorizeUrl);
FlowLayout flow = new FlowLayout(Component.TOP);
form.setLayout(flow);
form.addComponent(htmlC);
}
return form;
}
}
and i'm calling this method in my MIDlet class startApp() in following way
Login login=new Login();
login.Login().show();
I'm getting following errors
Uncaught exception!
java.lang.NullPointerException
at com.sun.lwuit.html.CSSEngine.applyStyleToUIElement(Unknown Source)
at com.sun.lwuit.html.CSSEngine.applyStyle(Unknown Source)
at com.sun.lwuit.html.CSSEngine.checkSelector(Unknown Source)
at com.sun.lwuit.html.CSSEngine.applyCSS(Unknown Source)
at com.sun.lwuit.html.CSSEngine.applyCSS(Unknown Source)
at com.sun.lwuit.html.CSSEngine.applyCSS(Unknown Source)
at com.sun.lwuit.html.CSSEngine.applyCSS(Unknown Source)
at com.sun.lwuit.html.CSSEngine.applyCSS(Unknown Source)
at com.sun.lwuit.html.CSSEngine.applyCSS(Unknown Source)
at com.sun.lwuit.html.CSSEngine.applyCSS(Unknown Source)
at com.sun.lwuit.html.CSSEngine.applyCSS(Unknown Source)
at com.sun.lwuit.html.HTMLComponent.applyAllCSS(Unknown Source)
at com.sun.lwuit.html.ResourceThreadQueue.threadFinished(Unknown Source)
at com.sun.lwuit.html.ResourceThreadQueue$ResourceThread.streamReady(Unknown Source)
at com.sun.lwuit.html.ResourceThreadQueue$ResourceThread.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
-VM verbose connection exited
The HttpRequestHandler file code is
/*
* Copyright � 2008, 2010, Oracle and/or its affiliates. All rights reserved
*/
package com.yoke.symbian;
import com.sun.lwuit.html.DocumentInfo;
import com.sun.lwuit.html.DocumentRequestHandler;
import com.yoke.helper.Storage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
/**
* An implementation of DocumentRequestHandler that handles fetching HTML documents both from HTTP and from the JAR.
* This request handler takes care of cookies, redirects and handles both GET and POST requests
*
* #author Ofir Leitner
*/
public class HttpRequestHandler implements DocumentRequestHandler {
//Hashtable connections = new Hashtable();
/**
* A hastable containing all cookies - the table keys are domain names, while the value is another hashtbale containing a pair of cookie name and value.
*/
static Hashtable cookies = Storage.getCookies();
/**
* A hastable containing all history - the table keys are domain names, while the value is a vector containing the visited links.
*/
static Hashtable visitedLinks = Storage.getHistory();
/**
* If true will cache HTML pages, this also means that they will be buffered and read fully and only then passed to HTMLComponent - this can have memory implications.
* Also note that for the cached HTMLs to be written Storage.RMS_ENABLED[TYPE_CACHE] should be true
*/
static boolean CACHE_HTML=false;
/**
* If true will cache images, this also means that they will be buffered and read fully and only then passed to HTMLComponent - this can have memory implications.
* Also note that for the cached images to be written Storage.RMS_ENABLED[TYPE_CACHE] should be true
*/
static boolean CACHE_IMAGES=true;
/**
* If true will cache CSS files, this also means that they will be buffered and read fully and only then passed to HTMLComponent - this can have memory implications.
* Also note that for the cached CSS files to be written Storage.RMS_ENABLED[TYPE_CACHE] should be true
*/
static boolean CACHE_CSS=false;
/**
* Returns the domain string we use to identify visited link.
* Note that this may be different than the domain name returned by HttpConnection.getHost
*
* #param url The link URL
* #return The link's domain
*/
static String getDomainForLinks(String url) {
String domain=null;
if (url.startsWith("file:")) {
return "localhost"; // Just a common name to store local files under
}
int index=-1;
if (url.startsWith("http://")) {
index=7;
} else if (url.startsWith("https://")) {
index=8;
}
if (index!=-1) {
domain=url.substring(index);
index=domain.indexOf('/');
if (index!=-1) {
domain=domain.substring(0,index);
}
}
return domain;
}
/**
* {#inheritDoc}
*/
public InputStream resourceRequested(DocumentInfo docInfo) {
InputStream is=null;
String url=docInfo.getUrl();
String linkDomain=getDomainForLinks(url);
// Visited links
if (docInfo.getExpectedContentType()==DocumentInfo.TYPE_HTML) { // Only mark base documents as visited links
if (linkDomain!=null) {
Vector hostVisitedLinks=(Vector)visitedLinks.get(linkDomain);
if (hostVisitedLinks==null) {
hostVisitedLinks=new Vector();
visitedLinks.put(linkDomain,hostVisitedLinks);
}
if (!hostVisitedLinks.contains(url)) {
hostVisitedLinks.addElement(url);
Storage.addHistory(linkDomain, url);
}
} else {
System.out.println("Link domain null for "+url);
}
}
String params=docInfo.getParams();
if ((!docInfo.isPostRequest()) && (params !=null) && (!params.equals(""))) {
url=url+"?"+params;
}
// See if page/image is in the cache
// caching will be used only if there are no parameters and no cookies (Since if they are this is probably dynamic content)
boolean useCache=false;
if (((docInfo.getExpectedContentType()==DocumentInfo.TYPE_HTML) && (CACHE_HTML) && ((params==null) || (params.equals(""))) && (!cookiesExistForDomain(linkDomain) )) ||
((docInfo.getExpectedContentType()==DocumentInfo.TYPE_IMAGE) && (CACHE_IMAGES)) ||
((docInfo.getExpectedContentType()==DocumentInfo.TYPE_CSS) && (CACHE_CSS)))
{
useCache=true;
InputStream imageIS=Storage.getResourcefromCache(url);
if (imageIS!=null) {
return imageIS;
}
}
// Handle the file protocol
if (url.startsWith("file://")) {
return getFileStream(docInfo);
}
try {
HttpConnection hc = (HttpConnection)Connector.open(url);
String encoding=null;
if (docInfo.isPostRequest()) {
encoding="application/x-www-form-urlencoded";
}
if (!docInfo.getEncoding().equals(DocumentInfo.ENCODING_ISO)) {
encoding=docInfo.getEncoding();
}
//hc.setRequestProperty("Accept_Language","en-US");
//String domain=hc.getHost(); // sub.domain.com / sub.domain.co.il
String domain=linkDomain; // will return one of the following formats: sub.domain.com / sub.domain.co.il
sendCookies(domain, hc);
domain=domain.substring(domain.indexOf('.')); // .domain.com / .domain.co.il
if (domain.indexOf('.',1)!=-1) { // Make sure that we didn't get just .com - TODO - however note that if the domain was domain.co.il - it can be here .co.il
sendCookies(domain, hc);
}
if (encoding!=null) {
hc.setRequestProperty("Content-Type", encoding);
}
if (docInfo.isPostRequest()) {
hc.setRequestMethod(HttpConnection.POST);
if (params==null) {
params="";
}
byte[] paramBuf=params.getBytes();
hc.setRequestProperty("Content-Length", ""+paramBuf.length);
OutputStream os=hc.openOutputStream();
os.write(paramBuf);
os.close();
//os.flush(); // flush is said to be problematic in some devices, uncomment if it is necessary for your device
}
String contentTypeStr=hc.getHeaderField("content-type");
if (contentTypeStr!=null) {
contentTypeStr=contentTypeStr.toLowerCase();
if (docInfo.getExpectedContentType()==DocumentInfo.TYPE_HTML) { //We perform these checks only for text (i.e. main page), for images/css we just send what the server sends
and "hope for the best"
if (contentTypeStr!=null) {
if ((contentTypeStr.startsWith("text/")) || (contentTypeStr.startsWith("application/xhtml")) || (contentTypeStr.startsWith("application/vnd.wap"))) {
docInfo.setExpectedContentType(DocumentInfo.TYPE_HTML);
} else if (contentTypeStr.startsWith("image/")) {
docInfo.setExpectedContentType(DocumentInfo.TYPE_IMAGE);
hc.close();
return getStream("<img src=\""+url+"\">",null);
} else {
hc.close();
return getStream("Content type "+contentTypeStr+" is not supported.","Error");
}
}
}
if ((docInfo.getExpectedContentType()==DocumentInfo.TYPE_HTML) ||
(docInfo.getExpectedContentType()==DocumentInfo.TYPE_CSS)) { // Charset is relevant for HTML and CSS only
int charsetIndex = contentTypeStr.indexOf("charset=");
if (charsetIndex!=-1) {
String charset=contentTypeStr.substring(charsetIndex+8);
docInfo.setEncoding(charset.trim());
// if ((charset.startsWith("utf-8")) || (charset.startsWith("utf8"))) { //startwith to allow trailing white spaces
// docInfo.setEncoding(DocumentInfo.ENCODING_UTF8);
// }
}
}
}
int i=0;
while (hc.getHeaderFieldKey(i)!=null) {
if (hc.getHeaderFieldKey(i).equalsIgnoreCase("set-cookie")) {
addCookie(hc.getHeaderField(i), url);
}
i++;
}
int response=hc.getResponseCode();
if (response/100==3) { // 30x code is redirect
String newURL=hc.getHeaderField("Location");
if (newURL!=null) {
hc.close();
docInfo.setUrl(newURL);
if ((response==302) || (response==303)) { // The "302 Found" and "303 See Other" change the request method to GET
docInfo.setPostRequest(false);
docInfo.setParams(null); //reset params
}
return resourceRequested(docInfo);
}
}
is = hc.openInputStream();
if (useCache) {
byte[] buf=getBuffer(is);
Storage.addResourceToCache(url, buf,false);
ByteArrayInputStream bais=new ByteArrayInputStream(buf);
is.close();
hc.close(); //all the data is in the buffer
return bais;
}
} catch (SecurityException e) {
return getStream("Network access was disallowed for this session. Only local and cached pages can be viewed.<br><br> To browse external sites please exit the application and when asked for network access allow it.", "Security error");
} catch (IOException e) {
System.out.println("HttpRequestHandler->IOException: "+e.getMessage());
return getStream("The page could not be loaded due to an I/O error.", "Error");
} catch (IllegalArgumentException e) { // For malformed URL
System.out.println("HttpRequestHandler->IllegalArgumentException: "+e.getMessage());
return getStream("The requested URL is not valid.", "Malformed URL");
}
return is;
}
/**
* Checks if there are cookies stored on the client for the specified domain
*
* #param domain The domain to check for cookies
* #return true if cookies for the specified domain exists, false otherwise
*/
private boolean cookiesExistForDomain(String domain) {
Object obj=cookies.get(domain);
//System.out.println("Cookies for domain "+domain+": "+obj);
if (obj==null) {
int index=domain.indexOf('.');
if (index!=-1) {
domain=domain.substring(index); // .domain.com / .domain.co.il
if (domain.indexOf('.',1)!=-1) { // Make sure that we didn't get just .com - TODO - however note that if the domain was domain.co.il - it can be here .co.il
obj=cookies.get(domain);
//System.out.println("Cookies for domain "+domain+": "+obj);
}
}
}
return (obj!=null);
}
/**
* Sends the avaiable cookies for the given domain
*
* #param domain The cookies domain
* #param hc The HTTPConnection
* #throws IOException
*/
private void sendCookies(String domain,HttpConnection hc) throws IOException {
//System.out.println("Sending cookies for "+domain);
Hashtable hostCookies=(Hashtable)cookies.get(domain);
String cookieStr="";
if (hostCookies!=null) {
for (Enumeration e=hostCookies.keys();e.hasMoreElements();) {
String name = (String)e.nextElement();
String value = (String)hostCookies.get(name);
String cookie=name+"="+value;
if (cookieStr.length()!=0) {
cookieStr+="; ";
}
cookieStr+=cookie;
}
}
if (cookieStr.length()!=0) {
//System.out.println("Cookies for domain "+domain+": "+cookieStr);
hc.setRequestProperty("cookie", cookieStr);
}
}
/**
* Returns an Inputstream of the specified HTML text
*
* #param htmlText The text to get the stream from
* #param title The page's title
* #return an Inputstream of the specified HTML text
*/
private InputStream getStream(String htmlText,String title) {
String titleStr="";
if (title!=null) {
titleStr="<head><title>"+title+"</title></head>";
}
htmlText="<html>"+titleStr+"<body>"+htmlText+"</body></html>";
ByteArrayInputStream bais = new ByteArrayInputStream(htmlText.getBytes());
return bais;
}
/**
* Adds the given cookie to the cookie collection
*
* #param setCookie The cookie to add
* #param hc The HttpConnection
*/
private void addCookie(String setCookie,String url/*HttpConnection hc*/) {
//System.out.println("Adding cookie: "+setCookie);
String urlDomain=getDomainForLinks(url);
// Determine cookie domain
String domain=null;
int index=setCookie.indexOf("domain=");
if (index!=-1) {
domain=setCookie.substring(index+7);
index=domain.indexOf(';');
if (index!=-1) {
domain=domain.substring(0, index);
}
if (!urlDomain.endsWith(domain)) { //if (!hc.getHost().endsWith(domain)) {
System.out.println("Warning: Cookie tried to set to another domain");
domain=null;
}
}
if (domain==null) {
domain=urlDomain; //domain=hc.getHost();
}
// Check cookie expiry
boolean save=false;
index=setCookie.indexOf("expires=");
if (index!=-1) { // Cookies without the expires= property are valid only for the current session and as such are not saved to RMS
String expire=setCookie.substring(index+8);
index=expire.indexOf(';');
if (index!=-1) {
expire=expire.substring(0, index);
}
save=true;
}
// Get cookie name and value
index=setCookie.indexOf(';');
if (index!=-1) {
setCookie=setCookie.substring(0, index);
}
index=setCookie.indexOf('=');
String name=setCookie;
String value="";
if (index!=-1) {
name=setCookie.substring(0, index);
value=setCookie.substring(index+1);
}
Hashtable hostCookies=(Hashtable)cookies.get(domain);
if (hostCookies==null) {
hostCookies=new Hashtable();
cookies.put(domain,hostCookies);
}
hostCookies.put(name,value);
if (save) { // Note that we save all cookies with expiry specified, while not checking the specific expiry date
Storage.addCookie(domain, name, value);
}
}
/**
* This method is used when the requested document is a file in the JAR
*
* #param url The URL of the file
* #return An InputStream of the specified file
*/
private InputStream getFileStream(DocumentInfo docInfo) {
String url=docInfo.getUrl();
// If a from was submitted on a local file, just display the parameters
if ((docInfo.getParams()!=null) && (!docInfo.getParams().equals(""))) {
String method="GET";
if (docInfo.isPostRequest()) {
method="POST";
}
String params=docInfo.getParams();
String newParams="";
if (params!=null) {
for(int i=0;i<params.length();i++) {
char c=params.charAt(i);
if (c=='&') {
newParams+=", ";
} else {
newParams+=c;
}
}
}
return getStream("<h2>Form submitted locally.</h2><b>Method:</b> "+method+"<br><br><b>Parameters:</b><br>"+newParams+"<hr>Continue to local URL","Form Results");
}
url=url.substring(7); // Cut the file://
int hash=url.indexOf('#'); //trim anchors
if (hash!=-1) {
url=url.substring(0,hash);
}
int param=url.indexOf('?'); //trim parameters, not relvant for files
if (param!=-1) {
url=url.substring(0, param);
}
// Use the following commented segment for loading HTML files saved with the UTF8 header added by some utils - 0xEF, 0xBB, 0xBF
// This is a simple code to skip automatically 3 chars on a certain file suffix (.htm isntead of .html)
// A better solution is to detect these bytes, but that requires buffering of the stream (to "unread" if these are not the right chars)
/*
if (url.endsWith(".htm")) {
System.out.println("Notepad UTF - Skipping 3 chars");
docInfo.setEncoding(DocumentInfo.ENCODING_UTF8);
// If the UTF8 encoding string doesn't work on your device, try the following instead of the line above:
//docInfo.setEncoding("UTF-8");
InputStream is= getClass().getResourceAsStream(url);
try {
is.read();
is.read();
is.read();
return is;
} catch (IOException ex) {
ex.printStackTrace();
}
}
*/
return getClass().getResourceAsStream(url);
}
/**
* Reads an inputstream completely and places it into a buffer
*
* #param is The InputStream to read
* #return A buffer containing the stream's contents
* #throws IOException
*/
static byte[] getBuffer(InputStream is) throws IOException {
int chunk = 50000;
byte[] buf = new byte[chunk];
int i=0;
int b = is.read();
while (b!=-1) {
if (i>=buf.length) {
byte[] tempbuf=new byte[buf.length+chunk];
for (int j=0;j<buf.length;j++) {
tempbuf[j]=buf[j];
}
buf=tempbuf;
}
buf[i]=(byte)b;
i++;
b = is.read();
}
byte[] tempbuf=new byte[i];
for (int j=0;j<tempbuf.length;j++) {
tempbuf[j]=buf[j];
There are numerous OAuth related bugs in LWUIT which we fixed for Codename One. Unfortunately there are so many its hard for me to tell which one you are triggering, however you can look at our issue tracker to see if you can find something specific. We still have some that are open but OAuth works MUCH better.