ClassCastException - java.lang.String cannot be cast to com.codename1.ui.Image - codenameone

I am consuming a JSON string that contains an image object among other objects. From this I create a PropertyBusinessObject which has a the following
public final Property<EncodedImage, Profile> profilePic = new Property<>("profilePic", EncodedImage.class);
I have created a method in the PropertyBusinessObject
public EncodedImage getProfilePic() {
return profilePic.get();
}
I populate my data into the Property business object as follows:
profile.getPropertyIndex().populateFromMap((Map) profileObject);
When I try to display the image on the form using the following code,
ScaleImageLabel profilePic = new ScaleImageLabel(profile.getProfilePic()) {
#Override
protected Dimension calcPreferredSize() {
Dimension dimension = super.calcPreferredSize();
dimension.setHeight(Math.min(dimension.getHeight(), Display.getInstance().convertToPixels(40)));
return dimension;
}
};
profilePic.setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FILL);
container.add(BorderLayout.NORTH, profilePic);
I get a ClassCastException
Exception: java.lang.ClassCastException - java.lang.String cannot be cast to com.codename1.ui.Image
Can anyone help me resolve, or suggest another way of consuming the JSON string?

populateFromMap doesn't currently support Base64 images, I'll add that as an option as that use case makes sense. Should be there with the Friday update.

Related

CodenameOne: PropertyIndex.toJSON() not generating correct JSON for Lists of Objects

I have a mobile app where a user fills out a form, say an Event, and when they save I want to submit the data as JSON to the server. CN1 has the feature to generate JSON easily using PropertyBusinessObject so my Event is defined as follows:
public class Event implements PropertyBusinessObject {
public final Property<Long, Event> eventId = new Property<>("eventId");
public final Property<EventLocation, Event> eventLocation = new Property<>("eventLocation", EventLocation.class);
public final Property<List<EventItinerary>, Event> eventItineraryList = new Property<>("eventItineraryList", XXX);
private final PropertyIndex idx...
}
Both EventLocation and EventItinerary implement PropertyBusinessObject and I've found that when I generate the JSON for Event, EventLocation generates fine but not EventItinerary. When I try and use EventItinerary.class in the "XXX" section above, I get the following error...
Exception: java.lang.ClassCastException - class java.util.ArrayList cannot be cast to class com.codename1.properties.PropertyBusinessObject
which occurs at line 484 of com.codename1.properties.PropertyIndex.toMapRepresentationImpl()
When I use List.class for "XXX" or nothing i.e. new Property<>("eventItineraryList"); then it posts to the server but the JSON contains the name of the class and its memory address i.e.
{
"eventId": 3425567,
"eventLocation" : {
...
},
"eventItineraryList": [
"com.myapp.event.EventItinerary#cdc543c",
"com.myapp.event.EventItinerary#39987ocb",
"com.myapp.event.EventItinerary#cd5t776c",
]
}
My question is what should I put in "XXX" to have the EventItinerary objects have the correct JSON representation?
You need to use a ListProperty so we can traverse into it and the ListProperty should refer to a different PropertyBusinessObject. So this should look roughly like this:
public final ListProperty<EventItinerary, Event> eventItineraryList = new ListProperty<>("eventItineraryList", EventItinerary.class);
Notice the EventItinerary.class which is important. The generic valuegets lost due to erasure. The argument lets us reconstruct the object with the right object types when loading from JSON.'
Also again, for this to work EventItinerary must be a PropertyBusinessObject too.

Is there any way to Convert byte array to String in modelAttribute?

I have a model class called "Post" which has an attribute "postContent" as a byteArray.
public class Post{
byte[] postContnet;
//getters
//setters
...
}
So, I am using spring boot and spring form tag for getting the user's input using modelAttribute. The reason I am using byte array is I am using Ckeditor to get the WYSIWYG content.
<form:form ...... modelAttribute="post">
...
<form:textarea path="postContect" id="editor1">
....
</form:form>
While inserting the post to DB, I did not convert anything and it is inserted in MySQL DB where the postContent column is Blob type. However, when I am retrieving the content back for the edit purpose, I am getting byte array rather it should be a String. In a controller, I am getting and sending the data to JSP as below:
....
Post post = postService.findByPostId(postId);
if (post != null) {
mv.addObject("title", "Edit Post");
mv.addObject("post", post);
...
So, when I use JSTL in JSP, it prints the postContect as an array. I could get many references where converting the String to byte array and wise versa but here since I am using spring form and modelAttribute I am not sure where should I edit. How could I get back String in between?
Thanks.
I have found out the answer and it works for me. I am adding the comment here because someone who has a similar issue will get an idea.
I created Spring converter for a string to byte array
#Component
public class StringBase64ToByteArray implements Converter {
#Override
public byte[] convert(String source) {
byte[] byteSource = null;
System.out.println("StringBase64ToByteArray is called");
try {
byteSource = Base64.getEncoder().encode(source.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return byteSource;
}
}
Then I created another converter to byte array to string
#Component
public class ByteArrayToStringBase64 implements Converter{
#Override
public String convert(byte[] source) {
byte[] decodedString = Base64.getDecoder().decode(source);
return new String(decodedString);
}
}
I have registered both converters to spring boot configuration
#Configuration
public class WebMvcConfig implements WebMvcConfigurer{
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new StringBase64ToByteArray());
registry.addConverter(new ByteArrayToStringBase64());
}
}

Solr-CustomTransformer For Converting Data from Database to table data

I am quite new to the solr custom transformer. I am trying to use solr custom customtransformer for preprocessing of the data fetched from Database.
The basic problem that, I am getting in using custom transformer, There is no change in the resultant row of solr after importing the data. I have checked that, Class is loaded and there is no error of
Error loading class of cust.test.pretransform
And In the transformer code, I just want the code to be reacted to the code.
public Object transformRow(Map<String, Object> row, Context context) {
// TODO Auto-generated method stub
List<Map<String, String>> fields = context.getAllEntityFields();
for (Map<String, String> field : fields) {
String textstruk_tec = field.get("field_tec");
if("name".equals(textstruk_tec))
{
String columnName = field.get(DataImporter.COLUMN);
Object values = row.get(columnName);
if(values != null)
{
row.put(textstruk_tec, "Textteil");
}
}
}
return row;
}
Thanks in advance !
Best Regards !

how to pass dataprovider to any test in testNG when dataset has data not specific to this testcase

I am trying to build a Selenium hybrid framework using TestNG wherein i am getting data from my excel datasheet. I am trying to use DataProvider of testNG, But problem is since my datasheet contains data which belongs to different test case (for eg. 2 rows for add user, 1 rows for modify user, some rows for searching user etc)
since my dataprovider will return all the data from datasheet and passing it to any particular testCase that will run for all row of dataprovider will cause problem (eg. create user will need 5 parameter but the data of edit user will not be sufficient to it).
how can we handle this problem?
Here's how you do this:
Within your .xls file, create a sheet which represents a particular functionality. (For e.g, login, compose, address-book etc., if I were to be taking the example of an emailing application)
Now each sheet would have test data for various test cases, that test out that particular functionality.
In your #Test method, you can create a new custom annotation (this would be a marker annotation), which would indicate the "sheet" name from which the data provider should be retrieving data from. If you are not keen on creating a new custom annotation, then you can make use of the "description" attribute of the #Test annotation to capture this information.
TestNG can natively inject a Method object to your #DataProvider annotated method. Here the Method object that was injected would represent the #Test method for which the data provider is about to be invoked. So now you can retrieve the sheet name, either from the new custom annotation (or) from the description attribute of the #Test annotation to figure out which sheet name to query for data.
That should solve your issue.
Here's a sample that demonstrates the overall idea. You would need to enrich the data provider, such that it uses the sheet name to query data from the excel spreadsheet. My sample just excludes all of that, for the sake of demonstration.
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
#Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
#Target({METHOD})
public #interface SheetName {
String value() default "";
}
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.lang.reflect.Method;
public class TestClass {
#Test(dataProvider = "dp")
#SheetName("one")
public void test1(String name) {
System.err.println("Name is " + name);
}
#Test(dataProvider = "dp")
#SheetName("two")
public void test2(int age) {
System.err.println("Age is " + age);
}
#DataProvider(name = "dp")
public Object[][] getData(Method method) {
String sheetName = getSheetName(method);
if (sheetName == null) {
// Handle the case, wherein our custom annotation is missing. That means the test perhaps
// expects
// either all of the data, or it could be a error case.
return new Object[][] {{}};
}
if ("one".equalsIgnoreCase(sheetName)) {
return new Object[][] {{"Cedric"}, {"Beust"}};
}
if ("two".equalsIgnoreCase(sheetName)) {
return new Object[][] {{1}, {2}};
}
// Handle the case, wherein we had a valid sheet name, but it represents a sheet that cant be
// found in our
// excel spreadsheet.
return new Object[][] {{}};
}
private String getSheetName(Method method) {
SheetName sheetName = method.getAnnotation(SheetName.class);
if (sheetName == null || sheetName.value().trim().isEmpty()) {
return null;
}
return sheetName.value();
}
}

iBatis unable to read property from Map when using isEqual

I'm seeing a very bizarre issue with iBatis when trying to read a property from a Java map using isEqual, but not with other iBatis operators. For example it is able to read the map properties fine when using isNotNull and iterate. The xml:
<isNotNull property="filterCriteria.account">
AND
id
<isEqual property="filterCriteria.account.meetsCriteria" compareValue="false">
NOT
</isEqual>
IN
(SELECT DISTINCT id
FROM account
WHERE some other criteria....
)
</isNotNull>
The 2 java classes we're using here:
public class SearchProfile {
private Map<String, SearchProfileCriteria> filterCriteria;
public SAOSearchProfile() {
filterCriteria = new HashMap<>();
}
public Map<String, SAOSearchProfileCriteria> getFilterCriteria() {
return filterCriteria;
}
public void setFilterCriteria(Map<String, SAOSearchProfileCriteriaBase> filterCriteria) {
this.filterCriteria = filterCriteria;
}
}
Above is the container object that is passed to iBatis for the querying, and below is the criteria object that will be the value of the map. In this example it is keyed with the String "account"
public class SearchProfileCriteria {
boolean meetsCriteria;
public String getCriteriaAsString() {
return StringUtils.getStringValueFromBoolean(meetsCriteria);
}
public boolean isMeetsCriteria() {
return meetsCriteria;
}
public void setMeetsCriteria(boolean meetsCriteria) {
this.meetsCriteria = meetsCriteria;
}
public String getSQLString(){
return meetsCriteria ? "" : "NOT";
}
}
And the exception:
Cause: com.ibatis.common.beans.ProbeException: There is no READABLE property named 'account' in class 'java.util.Map'; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:
The getSQLString() method was my half baked attempt at a work around, the String gets escaped in the query and throws a syntax error.
When I remove the <isEqual> block the query executes find, which indicates it is able to read the "account" key when checking the to see if it is null. As I mentioned above, we're also able to use the map keys in <iterate> tags without issue. It seems <isEqual> and <isNotEqual> are the only tags causing issues. Does anyone have experience with this or know what may be going on?
Beware: Using isNotNull, isEqual, iterate is iBatis, they don't exist anymore in Mybatis, so referencing to Mybatis indifferently is confusing.
Reference documentation.
For your issue, how does it behave if replacing Map with a class (property will be known at compile time)?
Or try using <isPropertyAvailable>.
The work around could work with right syntax: $ instead of #: $filterCriteria.account.SQLString$ instead of #filterCriteria.account.SQLString#, then the value is just concatenated instead of bound as parameter.

Resources