Confusing behavior of SimpleEvaluationContext.forReadOnlyDataBinding() in SpEL - spring-el

I am reading Spring 5.1.3 reference docs, and SpEL Type Conversion gets following sample code:
class Simple {
public List<Boolean> booleanList = new ArrayList<Boolean>();
}
Simple simple = new Simple();
simple.booleanList.add(true);
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
// false is passed in here as a string. SpEL and the conversion service
// correctly recognize that it needs to be a Boolean and convert it
parser.parseExpression("booleanList[0]").setValue(context, simple, "false");
// b is false
Boolean b = simple.booleanList.get(0);
It works as the documents mentioned, and changes the value of the property, but according to Javadocs forReadOnlyDataBinding()
Create a {#code SimpleEvaluationContext} for read-only access to public properties via {#link DataBindingPropertyAccessor}.
Shouldn't the SpEL Expression be read-only, and does not change the property value?

The field's contents are mutable but the field itself is immutable.
i.e. you are not allowed to replace booleanList with a new array but there is nothing to prevent the contents of the existing array from being mutated.

Related

What is the prototype of an object created after setting <constructor>.prototype to null? [duplicate]

If I write this
var o = Object.create(null)
alert(o instanceof Object) // this is false
How come this ends up being true
function o() {
}
o.prototype = null
alert(new o() instanceof Object) // this is true
Shouldn't manually setting the prototype to null cause it to inherit from nothing as Object.create does. Thanks in advance :-)
Briefly, if a constructor's prototype isn't an Object, then instances are given Object.prototype as their [[prototype]].
The detail is in ECMA-262, §13.2.2 [[Construct]]:
When the [[Construct]] internal method
for a Function object F is called with
a possibly empty list of arguments,
the following steps are taken:
Let obj be a newly created native ECMAScript object.
Set all the internal methods of obj as specified in 8.12.
Set the [[Class]] internal property of obj to "Object".
Set the [[Extensible]] internal property of obj to true.
Let proto be the value of calling the [[Get]] internal property of F
with argument "prototype".
If Type(proto) is Object, set the [[Prototype]] internal property of obj
to proto.
If Type(proto) is not Object, set the [[Prototype]] internal property of
obj to the standard built-in Object
prototype object as described in
15.2.4.
Let result be the result of calling the [[Call]] internal property
of F, providing obj as the this value
and providing the argument list passed
into [[Construct]] as args.
If Type(result) is Object then return result.
Return obj.
Noting that in items 6 and 7, null is Type null (ECMA-262 §8.2), it is not the same as typeof null, which is object.
When you instantiate it like that, it returns an object of o.
Its (hidden) prototype chain still points to Object

how to populate attribute via managed bean?

i have a jsf page with a form, i need to update an attribute of the form (current obviously) via a managed bean (via a button).
The managed bean in question already exists and do other code , which is uploading a file to the server and getting the full file path (it returns a string lets say file_name).
I want the attribute of the form (an input text named path) to get the file_name value each time a file is uploaded
There is multiple way to programmatically set a value of a view attribute in Oracle ADF, Here is two of them :
The JSF way using the highly recommended JSFUtils.java library function :
/**
* Method for setting a new object into a JSF managed bean
* Note: will fail silently if the supplied object does
* not match the type of the managed bean.
* #param expression EL expression
* #param newValue new value to set
*/
public static void setExpressionValue(String expression, Object newValue) {
FacesContext facesContext = getFacesContext();
Application app = facesContext.getApplication();
ExpressionFactory elFactory = app.getExpressionFactory();
ELContext elContext = facesContext.getELContext();
ValueExpression valueExp = elFactory.createValueExpression(elContext, expression, Object.class);
//Check that the input newValue can be cast to the property type
//expected by the managed bean.
//If the managed Bean expects a primitive we rely on Auto-Unboxing
Class bindClass = valueExp.getType(elContext);
if (bindClass.isPrimitive() || bindClass.isInstance(newValue)) {
valueExp.setValue(elContext, newValue);
}
}
JSFUtils.setExpressionValue("#{bindings.YOUR_VO_ATTRIBUTE.inputValue}","YOUR VALUE");
By binding the jsf component to your ADF Bean
Go To your component > Open property inspector > Set Binding Attribute to your Bean (will create the following getter and setter)
public void setMyInputText(RichInputText myInputText) {
this.myInputText = myInputText;
}
public RichInputText getMyInputText() {
return myInputText;
}
//then in your action you can just set and refresh component
this.setMyInputText(YourValue);
AdfFacesContext.getCurrentInstance().addPartialTarget(this.getMyInputText);
https://gist.github.com/CedricL46/6cc291ce80601f50b66973e1000690a9

How to create a read-only array in java?

I want to get rid of clone() method.
For the below class sonar (static code check tool) was complaining that
I should not directly expose an internal array of the object as one can change the array after the method call which in turn changes the object's state. It suggested to do a clone() of that array before returning so that object's state is not changed.
Below is my class...
class DevicePlatformAggregator implements IPlatformListings{
private DevicePlatform[] platforms = null;
public DevicePlatform[] getAllPlatforms() throws DevicePlatformNotFoundException {
if (null != platforms) {
return platforms.clone();
}
List<DevicePlatform> platformlist = new ArrayList<DevicePlatform>();
..... // code that populates platformlist
platforms = platformlist.toArray(new DevicePlatform[platformlist.size()]);
return platforms;
}
}
However I don't think its good to clone as its unnecessary to duplicate the data.
There is nothing similar to Collections.unmodifiableList() for array
I can not change the return type of the method getAllPlatforms() to some
collection as it is an interface method
I am not a Java guru but I am pretty confident that you are out of luck here. There is no way to make a primitive array immutable apart from creating an array of 0 elements.
Making it final won't help cause only the reference pointing to it would be immutable.
As you already said the way to go in obtaining an unmodifiable list would be to use Collections as in the following example:
List<Integer> contentcannotbemodified= Collections.unmodifiableList(Arrays.asList(13,1,8,6));
Hope it helps.

Java EE getResultList() return just object not relevant class type object

I am using this code to retrieve an object from a database. This code returns an object, but the type of that object is just Object.
I however want to return the type Pcinitialdata. As said, it returns just Object and the type of that is Object
How can I solve this?
String qryStrforCom = "select pci.fileNo,pci.projectNo,pci.fundId,pci.decrp,pci.devSec,pci.estBy,pci.areaCode,pci.targetDate,pci.jobnoRecedate,pci.conBy,pci.supBy,pci.ht33,pci.lt11,pci.sub11,pci.lt3Phase,pci.ltsPhase,pci.abc5w,pci.abc4w,pci.abcsecct,pci.perCapacity,pci.newCapacity,pci.proLtrToEsOn,pci.stdCost,pci.detailCost,pci.varianceNew from Pcinitialdata pci where TRIM(pci.estNo) = :value";
Query querycom = getEntityManager(webAppName).createQuery(qryStrforCom);
querycom.setParameter("value", value);
List<Pcinitialdata> listCom=querycom.getResultList();
if (listCom.isEmpty()) {
return null;
}
return listCom;
The query language that is used with the createQuery method is JPQL, not SQL.
In JPQL you can query directly for Entities, and there is no need to list all individual properties. Listing them anyway is supported, but the result is a list of separate properties and not a single entity.
Furthermore, you can enter a class type when you construct the Query object if you're using at least JPA 2.0 (Java EE 6). The code will then become:
String qryStrforCom = "select pci from Pcinitialdata pci where TRIM(pci.estNo) = :value";
TypedQuery<Pcinitialdata> querycom = getEntityManager(webAppName).createQuery(qryStrforCom, Pcinitialdata.class);
querycom.setParameter("value", value);
List<Pcinitialdata> listCom = querycom.getResultList();
if (listCom.isEmpty()) {
return null;
}
return listCom;
Note that with JPA you can chain calls and oftentimes it's better to work with empty lists instead of null. It's also more convenient to declare your query upfront, either in XML or via an annotation. Finally, try to cut down on the abbreviations used and give your variables meaningful names (e.g. value should not be called that if it's used for the estNo, etc.)
Your code would then become simply:
return getEntityManager(webAppName)
.createNamedQuery("Pcinitialdata.byEstNo", Pcinitialdata.class)
.setParameter("estNo", estNo)
.getResultList();

How to Set Exchange Body When Using Apache Camel JXPath Expression Language

I need to test whether the predicate object matches the exchange for various expression languages. I need to know what exchange value I need to set in exchange to validate the predicate.
public void test() {
String expression="//orders/value>10"';
CamelContext context = new DefaultCamelContext();
Predicate predicate=new JXpathExpression(expression,boolean.class);
Exchange exchange = new DefaultExchange(context);
Message in = exchange.getIn();
in.setBody(""); // how i need to set the message in exchange in order to evaluate it against predicate
exchange.setIn(in);
boolean check=predicate.matches(exchange);
}
For JXPath the predicate object contains JXpath[//orders/value>10] when I print it using predicate.toString().
How do I set the exchange so that this expression can be validated?
JXPath works on java objects. So you have to set a suitable object in the message body.
If the object you set there has o.getOrders().getValue() and returns a numeric value > 10 then the predicate should evaluate to true.

Resources