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;
}
Related
The actual code
package OOM.src.createOOM;
import org.eclipse.swt.internal.ole.win32.COM;
import com.sybase.stf.powerdesigner.PdCommon.*;
import com.sybase.stf.powerdesigner.PdOOM.*;
/**
* #author Xiao Wang
*
* This Java sample program shows how to use PowerDesigner Java proxies and
* OLE automation to create a PowerDesigner OOM model and display the contains of the OOM model.
*/
public class CreateOOM {
/** PowerDesigner application object */
private Application pdApp;
private int nbClasses;
/**
* Program entry point
*/
public static void main(String[] args) {
System.out.println("shhs");
// Create an instance of this class
CreateOOM createOOM1 = new CreateOOM();
// Create an OOM and display the result
createOOM1.CreateAndDisplayOOM();
}
/**
* Create an OOM and display the result
*/
public void CreateAndDisplayOOM() {
int hr = COM.OleInitialize(0);
try {
// Get PowerDesigner application instance and start PowerDesigner if necessary
pdApp = Application.getInstance();
if (pdApp != null)
{
// Create an OOM
Model newModel;
newModel = createOOM();
// Show the information of the current OOM
showOOMInfo();
// Release PowerDesigner application.
// This may close PowerDesigner if PowerDesigner was started by this program.
// pdApp.Release();
}
}
catch (Exception e) {
System.out.println("Cannot create PowerDesigner application object. Please verify that PowerDesigner is installed.");
}
finally {
if (hr == COM.S_OK)
COM.OleUninitialize();
}
}
/**
* Create an OOM for Java
*/
public Model createOOM() {
try {
// Create an OOM model, use Java as the language, create a default class diagram
// Convert the return object to PdOOM.Model proxy object
Model newModel = new Model(pdApp.CreateModel(PdOOM_Classes.cls_Model, "|Language=Java|Diagram=ClassDiagram"));
// set name and code
newModel.SetName("Customer Management");
newModel.SetCode("CustomerManagement");
//System.out.println("reach");
// Create a customer class.
// Use the fully qualified name here to avoid conflict with Java
com.sybase.stf.powerdesigner.PdOOM.Class newClass1 =
new com.sybase.stf.powerdesigner.PdOOM.Class(newModel.GetClasses().CreateNew());
newClass1.SetName("Customer");
newClass1.SetCode("Customer");
newClass1.SetComment("Customer class");
Attribute newAttribute;
// Create an id attribute
newAttribute = new Attribute(newClass1.GetAttributes().CreateNew());
newAttribute.SetName("Id");
newAttribute.SetCode("id");
// id is the primary identifier (primary key)
newAttribute.SetPrimaryIdentifier(true);
// set the Java data type
newAttribute.SetDataType("int");
// Create a name attribute
newAttribute = new Attribute(newClass1.GetAttributes().CreateNew());
newAttribute.SetName("Name");
newAttribute.SetCode("name");
// set the Java data type
newAttribute.SetDataType("java.lang.String");
// Create a phone attribute
newAttribute = new Attribute(newClass1.GetAttributes().CreateNew());
newAttribute.SetName("Phone");
newAttribute.SetCode("phone");
// set the Java data type
newAttribute.SetDataType("java.lang.String");
// Create an email attribute
newAttribute = new Attribute(newClass1.GetAttributes().CreateNew());
newAttribute.SetName("Email");
newAttribute.SetCode("email");
// set the Java data type
newAttribute.SetDataType("java.lang.String");
// Create an SalesOrder class.
// Use the fully qualified name here to avoid conflict with Java
com.sybase.stf.powerdesigner.PdOOM.Class newClass2 =
new com.sybase.stf.powerdesigner.PdOOM.Class(newModel.GetClasses().CreateNew());
newClass2.SetName("SalesOrder");
newClass2.SetCode("SalesOrder");
newClass2.SetComment("Sales order class");
// Create an orderId attribute
newAttribute = new Attribute(newClass2.GetAttributes().CreateNew());
newAttribute.SetName("Order id");
newAttribute.SetCode("orderId");
// id is the primary identifier (primary key)
newAttribute.SetPrimaryIdentifier(true);
// set the Java data type
newAttribute.SetDataType("int");
// Create an orderDate attribute
newAttribute = new Attribute(newClass2.GetAttributes().CreateNew());
newAttribute.SetName("Order date");
newAttribute.SetCode("orderDate");
// set the Java data type
newAttribute.SetDataType("java.util.Date");
// Create an association
Association association1 = new Association(newModel.GetAssociations().CreateNew());
// Set linked classes
association1.SetObject1(newClass1);
association1.SetObject2(newClass2);
// Set role A name and multiplicity
association1.SetRoleAName("customer");
association1.SetRoleAMultiplicity("1");
// Set role B name and multiplicity
association1.SetRoleBName("orders");
association1.SetRoleBMultiplicity("0..*");
// Get the default class diagram
ClassDiagram newDiagram = new ClassDiagram(newModel.GetDefaultDiagram());
// show the symbol in the default diagram if it is a class diagram
newDiagram.AttachObject(newClass1);
newDiagram.AttachObject(newClass2);
newDiagram.AttachLinkObject(association1);
return newModel;
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Display information about the currnt OOM
*/
public void showOOMInfo() {
try {
// Get the current OOM model
if (!pdApp.GetActiveModel().isNull())
{
if (pdApp.GetActiveModel().IsKindOf(PdOOM_Classes.cls_Model))
{
// Convert the active model to an OOM model proxy object
Model aModel = new Model(pdApp.GetActiveModel());
// Initialize the number of classes
nbClasses = 0;
// Display a message in PowerDesigner outut window
pdApp.Output("Display the list of classes in the system output window.");
// Show classes and packages defined under the model
// Convert model proxy object to package proxy object
showPackageInfo(new com.sybase.stf.powerdesigner.PdOOM.Package(aModel));
System.out.println("There are " + nbClasses + " class(es) in this model.");
}
else
{
System.out.println("The current model is not an OOM model.");
}
}
else
{
System.out.println("There is no active model opened in PowerDesigner.");
}
}
catch (Exception e) {
e.printStackTrace();
}
}
/**
* Display information about an OOM package
*/
public void showPackageInfo(com.sybase.stf.powerdesigner.PdOOM.Package aPackage) {
if (!aPackage.isNull() && !aPackage.IsShortcut())
{
// Display the number of classes and packages in the system output window
System.out.println("The " + aPackage.GetObjectType() + " '" + aPackage.GetCode() + "' contains " + aPackage.GetClasses().GetCount() + " class(es), " + aPackage.GetPackages().GetCount() + " package(s).");
// Use the fully qualified name here to avoid conflict with Java
com.sybase.stf.powerdesigner.PdOOM.Class aClass;
for (int n = 0; n < aPackage.GetClasses().GetCount(); n++)
{
nbClasses++;
if (nbClasses < 100)
{
// display class info
aClass = new com.sybase.stf.powerdesigner.PdOOM.Class(aPackage.GetClasses().Item(n));
showClassInfo(aClass);
}
else
{
if (nbClasses == 100)
System.out.println("...");
break;
}
}
// display classes of subpackages
com.sybase.stf.powerdesigner.PdOOM.Package subPackage;
for (int nPackage = 0; nPackage < aPackage.GetPackages().GetCount(); nPackage++)
{
subPackage = new com.sybase.stf.powerdesigner.PdOOM.Package(aPackage.GetPackages().Item(nPackage));
showPackageInfo(subPackage);
}
}
}
/**
* Display information about a class
*/
public void showClassInfo(com.sybase.stf.powerdesigner.PdOOM.Class aClass) {
try {
if (!aClass.isNull() && !aClass.IsShortcut())
{
System.out.println("Class No." + nbClasses + ": " + aClass.GetCode() + ", " + aClass.GetAttributes().GetCount() + " attribute(s), " + aClass.GetOperations().GetCount() + " operation(s)");
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
The issue im getting is--
org.eclipse.swt.SWTException: Action can not be performed. result = -2137456383 (com.sybase.stf.powerdesigner.com.COMException: COM Failure [HRESULT: 0x80990101])
at org.eclipse.swt.ole.win32.OLE.error(OLE.java:345)
at com.sybase.stf.powerdesigner.com.COMException.raiseOnFail(COMException.java:83)
at com.sybase.stf.powerdesigner.com.IDispatchEx.raisingInvoke(IDispatchEx.java:231)
at com.sybase.stf.powerdesigner.PdCommon.IApplication.CreateModel(IApplication.java:84)
at OOM.src.createOOM.CreateOOM.createOOM(CreateOOM.java:68)
at OOM.src.createOOM.CreateOOM.CreateAndDisplayOOM(CreateOOM.java:42)
at OOM.src.createOOM.CreateOOM.main(CreateOOM.java:28)
Caused by: com.sybase.stf.powerdesigner.com.COMException: COM Failure [HRESULT: 0x80990101]
at com.sybase.stf.powerdesigner.com.COMException.raiseOnFail(COMException.java:88)
... 5 more
There is no active model opened in PowerDesigner.
how can I resolve this?
So my application uses a number of TableViews within different FXMLViewControllers to present a number of different JPA Entities. The example below is for JobSupplierParts.
/**
* renderDoubleColumn takes a TableColumn setting its value and type before setting up edit event handling.
* #param column the tableColumn to be set up.
* #param field the name of the field to be mapped to.
* #param methodName the set method name of the field.
*/
protected void renderDoubleColumn(TableColumn<JobSupplierPart, Double> column, String field, String methodName) {
String className = "BiasDB.JobSupplierPart";
column.setCellValueFactory(new PropertyValueFactory<>(field));
column.setCellFactory(TextFieldTableCell.<JobSupplierPart, Double>forTableColumn(new DoubleStringConverter()));
column.setOnEditCommit(
new EventHandler<TableColumn.CellEditEvent<JobSupplierPart, Double>>() {
#Override
public void handle(TableColumn.CellEditEvent<JobSupplierPart, Double> t) {
JobSupplierPart supplierPart = t.getTableView().getItems().get(t.getTablePosition().getRow());
try {
Class<?> c = Class.forName(className);
Method method = c.getDeclaredMethod(methodName, Double.class);
method.invoke(supplierPart, t.getNewValue());
supplierPart.setTotal(updateItem(supplierPart));
} catch (ClassNotFoundException|NoSuchMethodException|IllegalAccessException|InvocationTargetException ex) {
logger.error("renderDoubleColumn",ex);
} //End try to get method from String.
try {
jobSupplierPartController.edit(supplierPart);
} catch (Exception ex) {
logger.error("renderDoubleColumn",ex);
}
t.getTableView().refresh();
}
} //END Event Handler
); //END SetOnEditCommit.
}
//END renderDoubleColumn
I can call this with:
renderDoubleColumn(discountColumn, "discount", "setDiscount");
BUT - I have to create new methods for each JPA Entity. Is it possible to replace the references to JobSupplierPart such that it becomes a generic method much like I have achieved with the methods? I have tried and alternatives such as T or K but they all returned errrors. The controller can just be passed as a parameter. Or is this a really bad practice/poor performance thing to do?
So I don't know if the Java aficionados will agree with this solution but in response to an answer posted and then deleted shortly after I was able to make the code cleaner. I also moved the set/edit section into a method so now I have:
/**
* renderBigDecimalColumn takes a TableColumn setting its value and type before setting up edit event handling.
* #param column the tableColumn to be set up.
* #param field the name of the field to be mapped to.
*/
private void renderBigDecimalColumn(TableColumn<AccountAsset, BigDecimal> column, String field) {
//Set an observable value for the column
column.setCellValueFactory(new PropertyValueFactory<>(field));
//Set how we want the cell to be rendered
// This line varies for the different cell types e.g. Strings, Bools etc.
column.setCellFactory(TextFieldTableCell.<AccountAsset, BigDecimal>forTableColumn(new BigDecimalStringConverter()));
//Set how we want the cell to be edited including the row update.
column.setOnEditCommit(t -> {
handleEditCommit(t, field);
}); //END SetOnEditCommit.
} //END renderBigDecimalColumn
And my handleEditCommit method looks like:
/** handleEditCommit deals with updating and saving the new data from the table view.
*
* #param t
* #param field
*/
private void handleEditCommit(javafx.scene.control.TableColumn.CellEditEvent<AccountAsset,?> t, String field) {
AccountAsset rowData = t.getTableView().getItems().get(t.getTablePosition().getRow());
//Set the new value.
try {
BeanUtils.setProperty(rowData, field, t.getNewValue());
} catch (IllegalAccessException | InvocationTargetException ex) {
logger.error("handleEditCommit / Setter", ex);
}
//Save the new rowData back to the database.
try {
tableDataController.edit(rowData);
} catch (Exception ex) {
logger.error("handleEditCommit / Edit", ex);
}
}
I think it would be useful to validate if an http request will be valid when using the details in the request to invoke a method.
I do not know of any apache library that has a method that I can use to do this but if there is one please let me know as it will make things a lot easier.
This is the code I have so far but it is really bad and also incomplete. I have left comments inside the code with which parts need to be completed but if something can be improved, please show me how.
package com.example.controller;
import java.io.IOException;
import java.util.Enumeration;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Test extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
System.out.println("has correct parameters: " + hasCorrectParameters(request));
request.getRequestDispatcher("index.jsp").forward(request, response);
} catch (Exception ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
/*
* This method will check if an HttpServletRequest has the correct parameters required to invoke a method
* ------------------------------------------------
* Potential problems and how they get resolved
* ------------------------------------------------
* 1. Too many parameters for any of the methods in the specified class
* SOLUTION: throw new ExcessiveParametersException().
* 2. Too few parameters for any of the methods in the specified class
* SOLUTION: throw new InsufficientParametersException().
* 3. Inappropriate method being called based on details provided
* SOLUTION: throw new IncorrectDetailsException().
* 4. No way of determining what will be returned and what's expected to be returned
* SOLUTION: ??
* 5. No way of determining which of the parameters in the request should be associated with which of the parameters in the method signature
* SOLUTION: ??
* 6. Parameters of the wrong type being passed to the method
* SOLUTION: Try and use instanceof to determine what the type of the parameter is. If it's not correct then throw new IncorrectDetailsException().
*/
public Boolean hasCorrectParameters(HttpServletRequest request) throws Exception {
//Class information
int methodWithMostParamsInSignature = 2;
int methodWithLeastParamsInSignature = 0;
//Request information
int paramsInRequest = 0;
Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()) {
String param = (String) parameterNames.nextElement();
System.out.println(param);
paramsInRequest++;
}
/*
* 1. Too many parameters for any of the methods in the specified class
* SOLUTION: throw new ExcessiveParametersException().
*/
if (paramsInRequest > methodWithMostParamsInSignature) {
throw new Exception("Excessive Parameters");
}
/*
* 2. Too few parameters for any of the methods in the specified class
* SOLUTION: throw new InsufficientParametersException().
*/
if (paramsInRequest < methodWithLeastParamsInSignature) {
throw new Exception("Insufficient Parameters");
}
/*
* 3. Inappropriate method being called based on details provided
* SOLUTION: throw new IncorrectDetailsException().
*/
if (request.getParameter("method") != null) {
if (request.getParameter("method").equalsIgnoreCase("isWalking")) {
if (paramsInRequest == 1) {
isWalking(Integer.parseInt(request.getParameter("speed")));
}
if (paramsInRequest == 2) {
if (request.getParameter("lastLocation") != null) {
isWalking(Integer.parseInt(request.getParameter("speed")), request.getParameter("lastLocation"));
}
}
}
}
/*
* 4. No way of determining what will be returned and what's expected to be returned
* SOLUTION: Not sure how to resolve
*/
/*
* 5. No way of determining which of the parameters in the request should be associated with which of the parameters in the method signature
* SOLUTION: Not sure how to resolve
*/
/*
* 6. Parameters of the wrong type being passed to the method
* SOLUTION: Try and use instanceof to determine what the type of the parameter is. If it's not correct then throw new IncorrectDetailsException().
*/
//Parameters are always a String so I'm not sure how to check if it's a valid variable for the method signature
return true;
}
public Boolean isWalking(Integer speed) {
return speed == 2;
}
public Boolean isRunning(Integer speed) {
return speed == 5;
}
public String isWalking(Integer speed, String lastLocation) {
if ((speed == 2) && (lastLocation.equalsIgnoreCase("nearby"))) {
return "Yup, you're walking";
}
return "";
}
}
You should use reflection to call the methods that you want to call. This will give a runtime exception when the wrong amount of parameters is provided.
Definition:
java.lang.reflect.Method method;
try {
method = obj.getClass().getMethod(methodName, param1.class, param2.class, ..);
} catch (SecurityException e) {
// ...
} catch (NoSuchMethodException e) {
// ...
}
Then to invoke:
try {
method.invoke(obj, arg1, arg2,...);
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
Api of Method: http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Method.html
In CDI 1.2 there is a way to check if a class instance is proxified? I need this because I need to get the name of original class, not the proxy name.
#Inject Bean bean;
public void sysout() {
// will print something like com.Bean$$Weld9239823
System.out.println(bean.getClass());
// I don't know how to check if the bean instance if a proxy or real class instance
}
Using Weld classes I can do this job:
public void sysout() {
// will print true because this is a proxy
System.out.println(ProxyObject.class.isAssignableFrom(bean));
// will print com.Bean
System.out.println(((TargetInstanceProxy) bean).getTargetInstance());
}
In CDI 1.1 there is no method to do this. I search inside CDI 1.2 docs if a method was added about this, but I don't found anything.
So... I miss something and CDI 1.2 there is a method to get original class name and instance? Or if not, there is a plain to add this feature in near feature?
For Weld on WildFly do this:
public boolean isProxy(Object obj) {
try{
return Class.forName("org.jboss.weld.bean.proxy.ProxyObject").isInstance(obj);
} catch (Exception e) {
log.error("Unable to check if object is proxy", e);
}
return false;
}
To retrive actual object instead of proxy (I need to serialize it) I do this:
public Object getObject(Object obj) {
Field f = null;
boolean isAccessible = false;
try {
for(Field fi : Class.forName(handler).getDeclaredFields()) {
if(fi.getName().equals(field)) {
f = fi;
isAccessible = f.isAccessible();
f.setAccessible(true);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
if(f == null) {
throw new RuntimeException(new NoSuchFieldException(String.format(
"The required field '%s' not found in '%s'. " +
"May be the code is obsolete for running on this application server.",
field, method)));
} else {
try{
obj = f.get(getHandler(obj));
for(Method m : Class.forName(instance).getMethods()) {
if(m.getName().equals(value)) {
return m.invoke(obj);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
f.setAccessible(isAccessible);
}
throw new NoSuchMethodError(String.format(
"The required method '%s' not found in '%s'. " +
"May be the code is obsolete for running on this application server.",
value, instance));
}
}
Be aware, that it is the darkest magic as possible, have very poor performance and can break at any WildFly update, if they change classes, methods for fields in it.
This is a terrible hack, but for Weld (and possibly other implementations) you can check if the class name contains "Proxy": possibleProxy.getClass().getSimpleName().contains("Proxy"). I use it only for logging purposes to get a cleaned up version of the wrapped class name:
/**
* Get the actual simple name of the objects class that might be wrapped by
* a proxy. A "simple" class name is not fully qualified (no package name).
*
* #param possibleProxy an object that might be a proxy to the actual
* object.
* #return the simple name of the actual object's class
*/
public static String getActualSimpleClassName(final Object possibleProxy) {
final String outerClassName = possibleProxy.getClass().getSimpleName();
final String innerClassName;
if (outerClassName.contains("Proxy")) {
innerClassName = outerClassName.substring(0, outerClassName.indexOf('$'));
} else {
innerClassName = outerClassName;
}
return innerClassName;
}
you can make a method inside your proxied cdi bean like
public String getClassName() {
return this.getClass().getName();
}
this is not the best solution, but a simple pragmatic way to get the class name through the proxy... the downside of this is that the method must be on every implementation...
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.