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.
Related
Using Java I am implementing a Page Factory object for selenium testing that takes the name of a page object and instantiates it through reflection for use by Cucumber step definitions. The problem I am having is that the code below cannot find the declared class. Both the object PageFactory which contains this code and the page object LoginPage reside in a package called pages.
/**
* This method take a string containing a Page Object class name (case-sensitive) and returns an instance of the Page Object.
* This allows us to operate on pages without knowing they exist when we write step definitions.
* #param choice String
* #return Page Object cast as a Page
*/
public static Page getPage(String choice) {
Page entity = null;
try {
entity = (Page) Class.forName(choice).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return entity;
}
I receive a stack trace with java.lang.ClassNotFoundException: LoginPage as the beginning of the error. If I change the entity creation to the following code, then it works.
private static String packageName = "pages";
entity = (Page) Class.forName(packageName + "." + choice).newInstance();
The problem is that I want to organize my pages. When I create pages.mywebsite and place LoginPage within that, PageFactory won't know where to find the file.
Leaving aside the problem that I could have two namespaces pages.mywebsite and pages.myotherwebsite that both have a LoginPage object, how can I find the files I want without declaring the exact package, and just say "Look in this package and the ones below for the class"?
You could get the classpath using System.getProperty("java.class.path"), split it around File.pathSeparator, and scan the results using FileVisitor.
This is how I solved my problem. I moved the reflection into a findPageInPackage method, and the called it recursively to search through directories.
Full code here: https://github.com/dougnoel/sentinel/blob/master/src/main/java/com/dougnoel/sentinel/pages/PageFactory.java
/**
* Returns a page object if it exists in the package searched.
* #param pageName String the name of the page object class to instantiate
* #param packageName String the name of the package to search
* #return Page the page object if it exists, otherwise null
*/
private static Page findPageInPackage(String pageName, String packageName) {
Page page = null;
try {
page = (Page) Class.forName(packageName + "." + pageName).newInstance();
} catch (InstantiationException e) {
log.trace("{}.{} Page Object creation failed.", packageName, pageName);
log.trace("java.lang.InstantiationException: {}", e.getMessage());
} catch (IllegalAccessException e) {
log.trace("{}.{} Page Object creation failed.", packageName, pageName);
log.trace("java.lang.IllegalAccessException: {}", e.getMessage());
} catch (ClassNotFoundException e) {
log.trace("{}.{} Page Object creation failed.", packageName, pageName);
log.trace("java.lang.ClassNotFoundException: {}", e.getMessage());
}
return page;
}
/**
* Returns the Page Object for the page name. This allows us to operate on pages
* without knowing they exist when we write step definitions.
* <p>
* Searches any optional page object packages set with the pageObjectPackages system property, and
* then searches the defaultPackageName value.
* <p>
* <b>Example:</b>
* <p>
* <code>System.setProperty("pageObjectPackages", "pages.SharedComponent,pages.UserAdminTool");</code>
*
* #param pageName String the name of the page in
* <a href="https://en.wikipedia.org/wiki/Camel_case">Pascal
* case</a>
* #return Page the specific page object cast as a generic page object
* #throws PageNotFoundException if page could not be built or retrieved.
* #throws ConfigurationNotFoundException if the value is not found in the configuration file
*/
public static Page buildOrRetrievePage(String pageName) throws PageNotFoundException, ConfigurationNotFoundException {
Page page = pages.get(pageName);
final String errorMessage = "The page you want to test could not be built. At least one Page object package is required to run a test. Please add a pageObjectPackages property to your conf/sentinel.yml configuration file and try again.";
if (page != null) {
return page;
} else {
if (pageObjectPackagesList == null) {
pageObjectPackagesList = ConfigurationManager.getPageObjectPackageList();
if(pageObjectPackagesList == null) {
throw new PageNotFoundException(errorMessage);
}
}
for (String pageObjectPackage : pageObjectPackagesList) {
log.trace("pageObjectPackage: " + pageObjectPackage);
page = findPageInPackage(pageName, pageObjectPackage);
if (page != null) {
break; // If we have a page object, stop searching.
}
}
}
if(page == null) {
throw new PageNotFoundException(errorMessage);
}
pages.put(pageName, page);
return page;
}
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"
}
}
}
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.
I'm doing a POC to push Data from a (Java) server, though LCDS 3.1 's DataService using RTMP.
Configuration is OK. Adobe Air client DataMessage to server (+Assembler saving in DB) : OK
I found lots of examples with AsyncMessage, but as This is an RTMP destination through a DataService service, I must send a DataMessage.
Appearently, there are some bugs (or I am missing things/good API doc!).
So please, could you help me?
Here is the code that does the push. The key method is doPush()
package mypackage.lcds.service.ds.impl;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import mypackage.lcds.service.ds.DataPushService;
import mypackage.model.dto.AbstractDto;
import mypackage.model.exception.DsPushException;
import flex.data.messages.DataMessage;
import flex.messaging.MessageBroker;
import flex.messaging.messages.Message;
import flex.messaging.services.MessageService;
import flex.messaging.util.UUIDUtils;
/**
* Implementation of {#link DataPushService}.
*/
// see http://forums.adobe.com/thread/580667
// MessageCLient :
// http://livedocs.adobe.com/livecycle/8.2/programLC/programmer/lcds/help .html?content=lcconnections_2.html
#Service
public final class DataPushServiceImpl implements DataPushService {
private static final Logger LOG = Logger.getLogger(DataPushServiceImpl.class);
/**
* Destination name for Data-service.<br>
* See data-management-config.XML.
*/
private static final String DESTINATION_NAME__POC_DS_XCHANGE = "poc-ds-xchange";
/**
* See data-management-config.XML.
*/
private static final String PUSH_DTO_SERVICE__NAME = "data-service";
/**
* set "manually" by Spring (contexts workaround; not autowired).
*/
private MessageBroker messageBroker = null;
/**
* Does the push of a single DTO.<br>
* Only subscriberId's that are {#link Long} values will be used. Other Id's do not get a Message sent.
*
* #param dto
* {#link AbstractDto} object.
* #param subscriberIds
* {#link Set} of LCDS Message subscriber IDs {#link Long}. If null, sends to all connected clients.
*
* #throws DsPushException
* if any error
*/
#SuppressWarnings("unchecked")
private void doPush(final AbstractDto dto, final Set<Long> subscriberIds)
throws DsPushException {
Set<?> ids = new HashSet<Object>();
// obtain message service by means of message broker
MessageService messageService = this.getMessageService();
DataMessage message = this.createMessage(dto, messageService);
// fill ids
if ((subscriberIds == null) || (subscriberIds.isEmpty())) {
if (LOG.isDebugEnabled()) {
LOG.debug("Sending message all currently connected subscriberIds ");
}
Set idsFromDS = messageService.getSubscriberIds(message, true);
if ((idsFromDS != null) && (!idsFromDS.isEmpty())) {
CollectionUtils.addAll(ids, idsFromDS.iterator());
}
} else {
CollectionUtils.addAll(ids, subscriberIds.iterator());
}
if (ids.isEmpty()) {
if (LOG.isDebugEnabled()) {
LOG.debug("No subscriberId to send the Message to.");
LOG.debug("Known subscribers : " + messageService.getSubscriberIds(message, true).toString());
}
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("Sending message to subscriberIds : " + subscriberIds.toString());
LOG.debug("Known subscribers : " + messageService.getSubscriberIds(message, true).toString());
}
// send messages to all subscriberIds 1 by 1
Object responsePayload = null;
boolean isSent = false;
for (Object id : ids) {
if (id instanceof Long) {
try {
message.setHeader(Message.DESTINATION_CLIENT_ID_HEADER, id);
if (LOG.isDebugEnabled()) {
LOG.debug("Sending LCDS DataMessage to subscriber [" + id + "] \n" + message.toString(2));
}
responsePayload = messageService.serviceMessage(message, true);
// no exception ==> means OK?
// TODO TEST retuned payload
isSent = true;
} catch (Exception e) {
LOG.error("Error while sending message to subscriberId " + id, e);
isSent = false;
} finally {
if (LOG.isDebugEnabled()) {
LOG.debug("Message sent to '" + String.valueOf(id) + "' : " + String.valueOf(isSent));
}
}
} else if (LOG.isDebugEnabled()) {
LOG.debug("Avoiding subscriber ID (not a Long value) : " + String.valueOf(id));
}
}
}
}
/**
* {#inheritDoc}
*
* #see DataPushService#pushToAllClients(AbstractDto)
*/
// TODO test : if client is not connected, does LCDS record it for later (offline mode on the server?)
public void pushToAllClients(final AbstractDto dto) throws DsPushException {
this.doPush(dto, null);
}
public void pushTo1Client(AbstractDto dto, Long subscriberId) throws DsPushException {
Set<Long> subscriberIds = new HashSet<Long>();
subscriberIds.add(subscriberId);
this.doPush(dto, subscriberIds);
}
/**
* {#inheritDoc}<br>
* subscriberIds refer to the 'clientId' set by the client app when it subscribes to the DS destination.
*
* #see DataPushService#pushToClients(AbstractDto, Set)
*/
public void pushToClients(final AbstractDto dto, final Set<Long> subscriberIds) throws DsPushException {
this.doPush(dto, subscriberIds);
}
#SuppressWarnings("unchecked")
private DataMessage createMessage(final AbstractDto dto, final MessageService messageService) {
DataMessage msg = new DataMessage();
msg.setClientId(getServerId());
msg.setTimestamp(System.currentTimeMillis());
msg.setMessageId(UUIDUtils.createUUID(true));
msg.setCorrelationId(msg.getMessageId()); // TODO OK messageId == CorrelationId ?
msg.setDestination(DESTINATION_NAME__POC_DS_XCHANGE);
msg.setBody(dto);
msg.setOperation(DataMessage.CREATE_AND_SEQUENCE_OPERATION); // TODO OK operation?
Map identity = new HashMap(2);
// see data-management-config.xml
identity.put("id", dto.getId());
msg.setIdentity(identity);
// FIXME set priority. How?
if (LOG.isDebugEnabled()) {
LOG.debug("LCDS DataMessage created : \n" + msg.toString(2));
}
return msg;
}
private Object getServerId() {
// FIXME OK?
return "X-BACKEND";
}
/**
* Get the current {#link MessageBroker}'s service layer.
*
* #return {#link MessageService} to use for push data
*/
private MessageService getMessageService() {
if (LOG.isDebugEnabled()) {
LOG.debug("Getting MessageBroker's DataService service ");
}
// Was : return (MessageService) MessageBroker.getMessageBroker(null).getService(PUSH_DTO_SERVICE__NAM E);
return (MessageService) this.messageBroker.getService(PUSH_DTO_SERVICE__NAME);
}
/**
* Set the messageBroker. For SPring.
*
* #param messageBroker
* the messageBroker to set
*/
public void setMessageBroker(final MessageBroker messageBroker) {
this.messageBroker = messageBroker;
}
}
NOTE : the messagebroker is set once through Spring. It works for this POC.
I have a Servlet that saves a DTO to the DB and then tries to push it through the service. All seems OK, but I get a NullPointerException (NPE).
Here is the Tomcat 6 LOG (it sends to subscriberID '99' ):
LCDS DataMessage created :
Flex Message (flex.data.messages.DataMessage)
operation = create_and_sequence
id = {id=3203}
clientId = X-BACKEND
correlationId = 7E6C3051-FA0F-9183-4745-B90ACACD71EA
destination = poc-ds-xchange
messageId = 7E6C3051-FA0F-9183-4745-B90ACACD71EA
timestamp = 1297412881050
timeToLive = 0
body = mypackage.model.dto.XchangeDto[id=3203[clientId=2[userId=123456[text= InterActionServlet Test]
09:28:01,065 DEBUG [impl.DataPushServiceImpl] Sending message to subscriberIds : [99]
09:28:01,065 DEBUG [impl.DataPushServiceImpl] Known subscribers : [99]
09:28:01,065 DEBUG [impl.DataPushServiceImpl] Sending LCDS DataMessage to subscriber [99]
Flex Message (flex.data.messages.DataMessage)
operation = create_and_sequence
id = {id=3203}
clientId = X-BACKEND
correlationId = 7E6C3051-FA0F-9183-4745-B90ACACD71EA
destination = poc-ds-xchange
messageId = 7E6C3051-FA0F-9183-4745-B90ACACD71EA
timestamp = 1297412881050
timeToLive = 0
body = mypackage.model.dto.XchangeDto[id=3203[clientId=2[userId=123456[text= InterActionServlet Test]
hdr(DSDstClientId) = 99
09:28:02,456 ERROR [impl.DataPushServiceImpl] Error while sending message to subscriberId 99
java.lang.NullPointerException
at flex.data.adapters.JavaAdapter.invokeAssemblerSync(JavaAdapter.java:1 741)
at flex.data.adapters.JavaAdapter.invokeBatchOperation(JavaAdapter.java: 1630)
at flex.data.adapters.JavaAdapter.invoke(JavaAdapter.java:658)
at flex.messaging.services.MessageService.serviceMessage(MessageService. java:318)
at flex.messaging.services.MessageService.serviceMessage(MessageService. java:233)
at mypackage.lcds.service.ds.impl.DataPushServiceImpl.doPush(DataPushSer viceImpl.java:142)
at mypackage.lcds.service.ds.impl.DataPushServiceImpl.pushTo1Client(Data PushServiceImpl.java:178)
at mypackage.servlet.InteractionServlet.push(InteractionServlet.java:75)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker. doInvokeMethod(HandlerMethodInvoker.java:421)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker. invokeHandlerMethod(HandlerMethodInvoker.java:136)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandle rAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:326)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandle rAdapter.handle(AnnotationMethodHandlerAdapter.java:313)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(Dispatch erServlet.java:875)
at org.springframework.web.servlet.DispatcherServlet.doService(Dispatche rServlet.java:807)
at org.springframework.web.servlet.FrameworkServlet.processRequest(Frame workServlet.java:571)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServl et.java:501)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Appl icationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationF ilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperV alve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextV alve.java:175)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.j ava:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.j ava:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineVal ve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.jav a:263)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java :844)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.proce ss(Http11Protocol.java:584)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:44 7)
at java.lang.Thread.run(Unknown Source)
09:28:02,472 DEBUG [impl.DataPushServiceImpl] Message sent to '99' : false
==> what am I doing wrong?
I cannot trace the code (I do not have the source), but the exception thrown is just not helping at all.
Am I missing a header to set?
Thank you so much for your help,
For the records, I found it ;o)
The base to know is that the DataServiceTransaction api is A MUST-HAVE, if you're using LC DataService.
For deails see Adobe forums thread
for the records here, here's my working (basic) code :
/**
* ASSUMPTION : the client Flex/Air apps set the desired userId (= filter) as a fillParameter of the
* DataService.fill() method. This will filter output based on {#link AbstractDto#getUserId()}.
*/
#Service
public final class DataPushServiceImpl implements DataPushService {
private static final Logger LOG = Logger.getLogger(DataPushServiceImpl.class);
/* *********** V2 : DataServiceTransaction.createItem() ********* */
/**
* Does the push of a single DTO.
*
* #param dto
* {#link AbstractDto} object. Contains the {#link AbstractDto#getUserId()} that is used by clients to
* filter data in the DataService.fill() method (used by the Assembler).
*
* #throws DsPushException
* if any error
*/
private boolean doPushViaTransaction(final AbstractDto dto) throws DsPushException {
if (LOG.isDebugEnabled()) {
LOG.debug("Sending message through DataServiceTransaction (see userId field) : " + dto.toString());
}
// One MUST instantiate a DataServiceTransaction to be able to send anything (NullPointerException)
DataServiceTransaction dtx = null;
boolean isOwnerOfTx = false;
boolean isSent = false;
try {
// if already in an Assembler, we do have a tx ==> no commit nor rollback!
dtx = DataServiceTransaction.getCurrentDataServiceTransaction();
if (dtx == null) {
// new one, no JTA ==> ourselves : commit or rollback
isOwnerOfTx = true;
//MessageBroker instantiated with SpringFlex is auto-named
dtx = DataServiceTransaction.begin("_messageBroker", false);
}
isSent = this.doTransactionSend(dto, dtx);
} catch (Exception e) {
// Log exception, but no impact on the back-end business ==> swallow Exception
LOG.error("Could not send the creation to LCDS", e);
if (isOwnerOfTx) {
dtx.rollback();
}
} finally {
try {
if (isOwnerOfTx && (dtx != null)) {
dtx.commit();
}
} catch (Exception e) {
// swallow
LOG.error("Could not send the creation to LCDS (#commit of the DataServiceTransaction)", e);
}
}
return isSent;
}
private boolean doTransactionSend(final AbstractDto dto, final DataServiceTransaction dtx) {
boolean isSent = false;
if (dto == null) {
LOG.error("The given DTO is null! Nothing happens");
} else {
try {
dtx.createItem(FlexUtils.DESTINATION_NAME__POC_DS, dto);
isSent = true; // no problem
} catch (Exception e) {
// Log exception, but no impact on the business
LOG.error("Could not send the creation to LCDS for DTO " + dto.toString(), e);
} finally {
if (LOG.isDebugEnabled()) {
LOG.debug("DTO : " + dto.toString() + "\n sent : " + String.valueOf(isSent));
}
}
}
return isSent;
}
//implementation of DataPushService interface
/**
* {#inheritDoc}
*
* #see DataPushService#pushNewDTo(AbstractDto, java.lang.Long)
*/
#Transactional(rollbackFor = DsPushException.class)
public boolean pushNewDTo(final AbstractDto dto, final Long subscriberId) throws DsPushException {
return this.doPushViaTransaction(dto);
}
}
Enjoy and thank you for your time!
G.