Combobox with BeanItemContainer and BeanFieldGroup throw Conversion exception - javabeans

I make some test to see how can bind combobox to some bean property, but i got an exception: "ConversionException: Could not convert value to String at ..........."
My sample work ok with indexedContainer for combobox, but i have some trouble with BeanItem container.
What i have:
1. TestCountry, simple java bean for BeanItemContainer (i don't put here setter and getter or constructor for simplicity):
public class TestCountry implements Serializable {
private String name;
private String shortName;
}
instantiation of BeanItemContainer
BeanItemContainer<TestCountry> _data = new BeanItemContainer<TestCountry>(TestCountry.class);
_data.addItem(new TestCountry("Afganistan","AF"));
_data.addItem(new TestCountry("Albania","AL"));
bean filed group. Here TestBean is another bean with simple string property's ("firstName","phone","contry")
BeanFieldGroup<TestBean> binder = new BeanFieldGroup<TestBean>(TestBean.class);
combobox
ComboBox myCombo = new ComboBox("Select your country", _data);
essential code
binder.bind(myCombo, "country");
When i try to commit the binder i got an error about conversion problem to string. From what i understand reading books and vaadin api, BeanItemContainer uses the beans themselves as identifiers and (here may be wrong) binder use item identifier to bind property. So here is the problem, conversion from Bean to string.
I try'it to implement toString(), hash() and equals() on my TestCountry bean but without success. What can do to use BeanItemContainer in this scenario?
Thanks in advance!!

You let your Vaadin application try to save a Bean (TestCountry) as a String in your TestBean.
That's fine, but then you have to approach it a little bit different. You have two options. You either change your datamodel, so the TestBean looks like this:
TestBean
firstName - String
phone - String
country - TestCountry (1:n)
now the TestBean will have a TestCountry stored instead of a String and your ComboBox shouldnt throw any more errors
or
you dont fill your ComboBox with Beans, but with Country strings, so the Vaadin application knows the datatype that is selected and what to save in your TestBean.
myCombo.addItem(getStringOfCountryYouWantToAdd())
...
then if you bind your String property "country" to the ComboBox which only contains Strings now, the binder will now how and what to save into "country".

Related

WinUI 3. Dependency injection in IValueConverter, using Microsoft.Extensions.DependencyInjection

I have a WinUI 3 app where we use Dependency-Injection from Microsoft.Extensions, and settings containing DateTime the current Date-Time formatting have been registered to the service collection as followed:
services.AddSingleton<IDateFormatService, DateFormatService>();
I'd like to just inject it into the constructor of the IValeConverter, but as it is constructed by the XAML the constructor must be empty.
Below is my current converter
public sealed class DateTimeFormatingConverter : DependencyObject, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value is not DateTime dateTime)
return value;
// return formatted dateTime based on settings formatting string
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
I know other injection libraries can allow this, as I've seen in this post and there for wondered if a likewise solution exist with the Microsoft extensions version.
I know it's a possibility to make a DependencyProperty and in XAML bind it to the dependency injected property in the viewmodel. However im looking into this as it would clean up the code substantially and while also removed multiple requirements from the converter that another developer won't easily know would be required.
I'd like to just inject it into the constructor of the IValeConverter, but as it is constructed by the XAML the constructor must be empty.
Correct.
The XAML processor engine doesn't know how to use Microsoft.Extensions to resolve dependencies so if you want to inject your converter with a constructor dependency that you register yourself, you must construct the converter programmatically (and not define it in the XAML markup).
You could for example do this in App.xaml.cs after you have registered the dependencies, e.g.:
this.Resources.Add("myConverter",
services.GetRequiredService<DateTimeFormatingConverter>());

jdto superclass boolean field binding incorrect value

public class Model {
}
public class SuperclassDTO {
private boolean funny = true;
public boolean isFunny() {
return funny;
}
public boolean setFunny(boolean f) {
this.funny = f;
}
}
public class SubclassDTO extends SuperclassDTO {
}
new SubclassDTO().isFunny() //returns true
SubclassDTO dto = binder.bindFromBusinessObject(SubclassDTO.class, new Model());
dto.isFunny(); //returns false!!!!
Isn't this weird? Model class does not have a "funny" field but somehow dto is bind with a wrong value. First I thought jDTO required "getFunny" convention, so it couldn't read the value and just set it "false" but changing the getter name to "getFunny" does not resolve the issue, plus I'm not allowed to modify SuperclassDTO. How can I bind the correct value?
Jdto version 1.4 by the way...
The behavior you're experiencing is a "side effect" of the convention over configuration approach. All the fields on the DTO are configured unless you mark them as transient, either by using the #DTOTransient annotation or the transient configuration on the XML file. If a configured field does not have a corresponding field on the source bean, it will be set with default values and that is the reason why you're experiencing this behavior.
You have some options to overcome this issue:
Add the #DTOTransient annotation to the DTO.
Since you're not able to modify the DTO, you could configure it through XML.
Use Binding lifecycle to Restore the value. By adding code on the subclass.
You might as well submit a bug report on the jDTO issue tracker on github.

struts2: select tag doesn't like beans with "parameters" property?

I have a base class ReportElement which has type property:
public abstract class ReportElement {
private ReportElementType type;
public ReportElementType getType() {
return type;
}
public void setType(ReportElementType type) {
this.type = type;
}
}
ReportElementType is just an enum with specified code and i18nKey properties for each element. I have a couple of subclasses of ReportElement, each of them introducing their own properties. One of them is Plot:
public class Plot extends ReportElement {
public Plot() {
setType(ReportElementType.PLOT);
}
private Collection<Parameter> parameters = new ArrayList<Parameter>();
public Collection<Parameter> getParameters() {
return parameters;
}
}
On some page I needed to display a collection of different ReportElement instances, so I just used struts2 select tag:
<s:select list="myElements" listKey="type.code" listValue="type.i18nKey" size="20"/>
This worked like a charm for every element except for Plot instaces. Instead of invoking getType().getCode() or getType().getI18nKey() plain toString() was invoked on every instance of Plot! After several hours of fun debugging I noticed that during tag evaluation Plot's getParameters() method is called! So it seems struts was trying to evaluate type.code and type.i18nKey using getParameters() method! Failing to do that it ignored the existence of the properties, that I have clearly specified for usage!
After renaming getParameters to a kind of odd name like getParamms the problem gone. Also the problem hasn't occured when using iterator tag together with property tag instead of select tag.
Does anyone have an idea WHY struts select tag uses parameters property of my bean, when I have clearly specified what property should be used? Is it some "cool" feature or a bug?
P.S. I use struts 2.2.3.1
The argument used in all the FreeMarker templates representing a tag's parameters is called parameters. By providing a parameters property that takes precedence, S2 was unable to get to the object on the stack containing the tag's parameters.
It's neither a cool feature nor a bug, it's just how the templates are implemented. Checking the template source may have saved the few hours of debugging.
Found corresponding issue in struts JIRA: https://issues.apache.org/jira/browse/WW-3268
2.3 is specified as fix version.

What are the parameters for the Salesforce WebServiceCallout.invoke method?

I would like to know the parameters for the invoke method used by Salesforce to invoke remote web services. I have a service that I'm suposed to be able to invoke, but the service WSDL does not define the security requirements, so I'm hoping I can add that information manually (The services uses WS-Security passed through Soap headers).
Here is what I (think I) know so far:
WebServiceCallout.invoke(
Class servicePort, //Usually set to "this", contains httpheader info as well as ?
request_x, //Request object, defining schema, properties, and field order
response_map_x, //Response object, defining schema, properties, and field order
new String[]{
String endpoint, //Endpoint of the service
String ?, //what is this?
String methodSchema, //Schema for the request object?
String method, //Name of the request method?
String responseSchema, //Schema for the response object?
String response, //Name of the response object?
String responseClass} //Name of the Apex class the response will be converted to
);
Can anyone help fill in the gaps?
Here's what I have discovered so far for WebServiceCallout.invoke:
Object servicePort - A class with the following variables:
String enpoint_x: containing the service endpoint (not sure if necessary)
Map<String,String> inputHttpHeaders_x: custom httpHeaders
Map<String,String> outputHttpHeaders_x: I think this is the httpHeaders that were returned
String clientCertName_x: Used in configuring an SSL cert?
String clientCert_x: Used in configuring an SSL cert?
String clientCertPassword: Used in configuring an SSL cert?
Integer timeout_x: How long (in milliseconds?) to wait for the response
String[] ns_map_type_info: The first String is the namespace of the service schema, the second is the name of the object that contains the Apex classes defining the schema objects
Object request_x - The Apex object that will form the XML schema object
Map<String, Object> response_map_x - Object is the object that the result is to be unserialized into. String is the name of Object variable.
String[] {
endpoint - The service endpoint
soapAction - If the service call requires a soapAction, put it here. Otherwise leave blank.
methodSchema - Schema for the request object
method - Name of the request method
responseSchema Schema for the response
responseClass The Apex class that the response will be unserialized into
}
In addition, Soap headers can be inserted by creating an object in the servicePort class as well as
a String with the same variable name+"_hns" that specifies the namespace for that object:
public SoapSecurity Security;
private String Security_hns = "Security=http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
The apex XML Schema objects should contain variables for each child element (or attribute). Arrays whose variable names match certain patterns define how the object variables are used in the xml.
Given the following example XML:
<foo a="b"><bar>baz</bar></foo>
The Apex classes would be something like this:
public class MyService {
public class bar {
public String bar;
private String[] bar_type_info = new String[] {'bar','http://www.w3.org/2001/XMLSchema','string','0','1','true'};
private String[] apex_schema_type_info = new String[] {'http://schema.myservice.com', 'false', 'false'};
private String[] field_order_type_info = new String[] {'bar'};
}
public class foo {
public MyService.bar bar;
public String a;
private String[] bar_type_info = new String[] {'bar','http://schema.myservice.com','bar','0','1','true'};
private String[] a_att_info = new String[] {'a'};
private String apex_schema_type_info = new String[] {'http://schema.myservice.com','false','false'};
private String[] field_order_type_info = new String[] {'bar'};
}
}
Here's a (brief) breakdown of these objects:
If the variable represents another XML element or a text node, then there needs to be a matching _type_info String[] e.g. bar_type_info. The elements of this array are:
1. XML element name
2. Schema
3. XML type
4. minOccurs
5. maxOccurs (set to '-1' for unbounded)
6. isNillable
If the variable represents an attribute, then there must be a matching _att_info String[] e.g. a_type_info. Thise simply contains the XML name of the attribute.
Note that if an class variable name is a reserved word, then _x is appended to it e.g. bar_x. This would affect the other variables names: bar_x_type_info. The Apex Developer's Guide explains their rules for names, but if you are manually creating it, I think you can give it whatever name you want--the arrays determine the XML element name...
I have not found a way to represent a simple XML type that also contains an attribute: e.g.
<foo bar="baz">bar</foo>
The apex_schema_type_info array specifies information about the XML element represented by the class:
1. Schema
2. 'true' if elementFormDefault="qualified"
3. 'true' if attributeFormDefault="qualified"
I'm still rather fuzzy on what 2 and 3 actually do, but it seems to affect how child elements (and attributes) inherit the parent namespace (whether it's implied or must be specified in the resulting XML).
field_order_type_info simply specifies the order of the child elements.
Please feel free to correct or clarify...
There is the Force.com Apex Code Developers Guide - Understanding the Generated Code, but it is currently fairly sparse on details for WebServiceCallout.invoke(...).
There is also Apex Web Services and Callouts, again not any useful details.
Up-voting Ideas: Documentation for WebServiceCallout may help in the long run.
Salesforce have just done an opensource release of wsdl2apex on Github, so you can now check to code to see exactly what is occurring. Announcing the Open-Source WSDL2Apex Generator

WCF Read DataMember Name attribute

I have a very simple class called person.
public class Person{
[DataMember(Name="MyName")]
public string Name { get;set;}
}
If I try to serialize or de-serialize, everything works great. In the XML I can see a tag called "MyName" and in the object I see with the VS Intellisense a property called Name.
What I need now is to access, from the object, the serialized name of the property.
For example, I can do object.GetType().GetProperty("Name"); but if I try to do object.GetType().GetProperty("MyName"), the reflection says that the property does not exist. How I can read the serialized name of the property? Is there a way?
It seems that the only way is to access, using reflection, the attributes of the property in this way:
var att = myProperty.GetType().GetAttributes();
var attribute = property.GetCustomAttributes(false)[0] as DataMemberAttribute;
Console.WriteLine(attribute.Name);
This works on both, client and server, without the need of serialize and deserialize the object.