addPropertyNode - equivalent in version 1.0? - bean-validation

Relatively simple probably. The Java 7 documentation for the ConstraintViolationBuilder interface specifies:
addNode
ConstraintValidatorContext.ConstraintViolationBuilder.NodeBuilderCustomizableContext addNode(String name)
Deprecated. since 1.1 - replaced by addPropertyNode(String) and addBeanNode()
Adds a node to the path the ConstraintViolation will be associated to. name describes a single property. In particular, dot (.) is not allowed.
"Now" the documentation also includes the methods mentioned.
I had a requirement to validate some data using this, and the code is running on a JBoss AS 7.1.1-Final.
The "Getting Started"-Page of jBoss 7 mentions: "Java SE 7 can be used with JBoss AS 7". Now what I want to achieve is simple:
I have a Validator implements ConstraintValidator<AnnotationType, DomainClass>, there I want to create a nice-looking ConstraintViolationException, that can be nicely handled by JSF / Primefaces to show a message and mark a field as invalid, but alas:
#Override
public boolean isValid(DomainClass instance, ConstraintValidatorContext context) {
// validation logic
if (valid) {
return true;
} else {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(message)
.addPropertyNode("locationName").addConstraintViolation();
return false;
}
}
And here's where it gets problematic... As mentioned in the documentation linked above: addPropertyNode() is only available as of version 1.1 of the Bean Validation. Unfortunately JBoss AS 7 just includes BeanValidation version 1.0 (as visible in Getting Started Page).
I analyzed stacktraces of working validations, and saw, the propertyPath in ConstraintViolationImpl instances (as used by hibernate) uses multiple dots.
The documentation explicitly states: "In particular, dot (.) is not allowed.".
There's two possiblities now:
Change the application server to Wildfly (or similar, where JSR 349 is implemented)
Solve the problem using JSR 303 only using the addNode()-method.
For the purpose of this question, we rule out possibility 1 (impractical, possible required work).
How would I do this using Bean Validation 1.0?
In particular what is required in the placeholder for this to work properly with JSF Faces-Validation:
#Override
public boolean isValid(DomainClass instance, ConstraintValidatorContext context) {
// validation logic
if (valid) {
return true;
} else {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(message)
.addNode(/* Some awesome String */).addConstraintViolation();
return false;
}
}
Or last but not least, I am totally ... and overread a simpler approach to this :(

It seems the last option actually is the correct one :( I am dumb I am missing the forest for the trees...
What is not quite obvious from the documentation: The .addNode() calls are supposed to be chained!
#Override
public boolean isValid (DomainClass instance, ConstraintValidatorContext context) {
//validation logic
if (valid) {
return true;
} else {
context.disableDefaultConstraintViolation();
context.buildConstrainViolationWithTemplate(message)
.addNode("tree").addNode("nodes").addNode("to")
.addNode("property").addConstraintViolation();
return false;
}
}
This solves my problem. Additionally I want to mention here, that the JSR-303 Section 4.2 - Constraint Violation defines the correct rules for building the propertyPath:
Path is made of Nodes and is built according to the following rules:
if the failing object is the root object, a Node with name set to null is added to the Path.
When an association is traversed:
a Node object whose name equals the name of the association property (field name or Java Bean property name) is added to Path
if the association is a List or an array, the following Node object added contains the index value in getIndex.
if the association is a Map, the following Node object added (representing a given map entry) contains the key value in getKey
for all Iterable or Map, the following Node object added is marked as inIterable (isInIterable)
For a property level constraint (field and getter)
a Node object is added to Path whose name equals the name of the property (field name or Java Bean property name)
the property path is considered complete
For a class level constraint:
a Node object is added to Path whose name is null
the property path is considered complete

Related

ActivatorUtilities.CreateInstance giving "A suitable constructor not found" for simple examples

So I am building a complex case here with inheritance and IOC, need to use ActivatorUtilities to inject instances and pass parameters... no matter what I do I get the following error:
System.InvalidOperationException: 'A suitable constructor for type
'blabla.ISimpleTest' could not
be located. Ensure the type is concrete and all parameters of a public
constructor are either registered as services or passed as arguments.
Also ensure no extraneous arguments are provided.'
So in order to discard what could be the problem and ensure there is no constructor issues, I created a very very simple scenario that gives me the same error.
startup.cs
services.AddScoped<ISimpleTest, SimpleTest>();
the class and the interface, very simple here:
public interface ISimpleTest
{
}
public class SimpleTest : ISimpleTest
{
public SimpleTest()
{
}
}
test
var theInstance = ActivatorUtilities.CreateInstance<ISimpleTest>(ServiceProvider);
Additional notes
The ServiceProvider instance is fine (the rest/entire application depends on it).
Tried with and without adding the public constructor(empty params)
Tried also constructor with params, same error.
Tried to specify the params[] parameter, by sending null or empty array, same issue.
Extra test:
Just to confirm it's properly registered, I tried to get the instance using the Service provider, and works without issues:
//No issues this way:
var yyy = ServiceProvider.GetService<ISimpleTest>();
What am I doing here wrong? According to documentations, this should be enough to work

Magnolia - Cross field validation

We have below requirement.
Field 1 : comboBoxField and it is mandatory.
Field 2: comboBoxField
Case 1. If editor choose field 1 value is "value1", then field 2 is mandatory
Case 2: if editor choose Field 1 value is "value2", then filed 2 is optional.
How to do this validation either in form/field validation before commit action.
Or how do we validate in commit action.
Any lead will help me a lot. I am stuck in this issue for longtime.
I tried with cross-field, dynamic filed , switchable and composite field as suggested in documentation, but I got null pointer exceptions. If you know the solution please share code snippet also.
I also suffered with this type of validation. The problem is in the isolation of the fields. I couldn't find a way to validate one field depending on another field value.
Anyway I found a workaround solution. I aggregate two dependent fields with complex field and create a validator for it.
Here's my code for the Magnolia 5.7 and vaadin validator (it's deprecated 7th version, nevertheless the logic will be the same with the 8th version).
public class CompanyRequiredFieldsValidator implements Validator {
private final ConfiguredFieldValidatorDefinition definition;
public CompanyRequiredFieldsValidator(ConfiguredFieldValidatorDefinition definition) {
this.definition = definition;
}
#Override
public void validate(Object value) throws InvalidValueException {
Optional<String> companyName = getString(value, "companyName");
if (companyName.isPresent()) {
getString(value, "companyAddress")
.orElseThrow(() -> new InvalidValueException(definition.getErrorMessage()));
}
}
private Optional<String> getString(Object value, String property) {
return Optional.of(value)
.filter(Item.class::isInstance).map(Item.class::cast)
.map(_v -> _v.getItemProperty(property))
.map(Property::getValue)
.filter(String.class::isInstance).map(String.class::cast)
.filter(StringUtils::isNotEmpty);
}
}
For complex fields validated value has com.vaadin.v7.data.Item type, so it's possible to get all properties from it.
The only problem, that the error message does not highlight the inner field, only whole complex field.

Web API .net core Attribute routing with FromQuery

I have below code implemented Web API (.net Framework 4.5.2). When I make a call "http://localhost:3000/123" - It fetches user details whose id is 123.
If I make "http://localhost:3000/Class1/?status=Active" - It fetches user details who belong to Class 1 and status as active. Same I converted to .net core and eventhough I mentioned FromQuery, call always goes to ":http://localhost:3000/123"
public class UserController : Controller
{
private Repository repository;
[HttpGet("{id}")]
public object Get(string id)
{
return repository.GetUser(id) ?? NotFound();
}
[HttpGet("{group}")]
public object Get(string group, Status status)
{
// Get the User list from the group and whose status is active
}
}
Please let me know how to resolve this without changing Route Parameter.
Simply, you have two conflicting routes here. There's no way for the framework to know which to route to, so it's just going to take the first one. As #Nkosi indicated, if there's some kind of constraint you can put on the param, that will help. You may not be able to restrict to just ints, but perhaps there's a particular regex, for example, that would only match one or the other. You can see your options for constraining route params in the relevant docs.
If there's no clear constraint you can apply that will not also match the other, then you're mostly out of luck here. You can simply change one of the routes to be more explicit, e.g. [HttpGet("group/{group}")]. If the route absolutely must be the same, your only other option is to have one action handle both cases, branching your code depending on some factor.
[HttpGet("{id}")]
public object Get(string id, Status? status = null)
{
if (status.HasValue)
{
// Note: treat `id` as `group` here.
// Get the User list from the group and whose status is active
}
else
{
return repository.GetUser(id) ?? NotFound();
}
}
That may not be the best approach (branching on presence of status), but it's just an example. You'd need to decide what would work best here.

Chain Of Command (method wrapping) in D365FO results in 'Object is not set to an instance of an object'

I am trying to use the new 'Chain Of Command' feature in D365FO by extending CustTable.
We need to check if a value has changed on the update method, before we log it in a new table.
[ExtensionOf(tableStr(CustTable))]
final class CustTable_Extension
{
void update(boolean _updateSmmBusRelTable = true, boolean _updateParty =
true)
{
CustTable custTable_Orig = this.orig();
boolean hasChanged = this.CreditMax != custTable_Orig.CreditMax;
next update(_updateSmmBusRelTable, _updateParty);
if(hasChanged)
{
//do something
}
}
}
However when running this code we get "Object is not set to an instance of an object" error. The error occurs because 'this' object is null. I also get the same error when calling "next update(_updateSmmBusRelTable, _updateParty);".
The documentation states: "This allows extending the logic of public and protected methods without the need to use event handlers. When you wrap a method, you can also access other public and protected methods and variables of the class."
Any ideas?
You have to (re-)compile package with CustTable - Application Suite with PU9 or newer.
See https://learn.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/get-started/whats-new-platform-update-9#supported-versions:
However, this functionality requires the class being augmented to be compiled on Platform update 9. Because the current releases of the Dynamics 365 for Finance and Operations, Enterprise editon applications have been compiled on Platform update 8 or earlier, you will need to recompile a base package (like Application Suite) on Platform update 9 or newer in order to wrap a method that is defined in that package
Try removing default parameters value from your wrapper method.
[ExtensionOf(tableStr(CustTable))]
final class CustTable_Extension
{
void update(boolean _updateSmmBusRelTable , boolean _updateParty )
{
CustTable custTable_Orig = this.orig();
boolean hasChanged = this.CreditMax != custTable_Orig.CreditMax;
next update(_updateSmmBusRelTable, _updateParty);
if(hasChanged)
{
//do something
}
}
}
I know that a long time passed on since the question was ask, but this one was a bug in Platform Updates lower than 13. This error fired in cases where a Form and a Table with the same name existed.
It was fixed with PU13.

Why some VariableDeclaration resolveBinding returns null but others does not

I am developing an eclipse plug-in to analyze the java source code. I traverse the whole AST tree and write a visitor to visit each variableDeclartionStatement, I noticed for some variables, the "resolvebinding" return an instance of IVariableBinding, but others does not. I can not differentiate them. BTW: I have set the ASTParser.setKind(K_COMPILATION_UNIT) and setResolveBindings(true). My code is as follows:
#Override
public boolean visit(VariableDeclarationStatement vStatement) {
Type theType = vStatement.getType();
for(Iterator iterator = vStatement.fragments().iterator();iterator.hasNext();){
VariableDeclarationFragment fragment = (VariableDeclarationFragment)iterator.next();
IVariableBinding binding = fragment.resolveBinding();
if(binding !=null){
ITypeBinding tBinding = binding.getType();
if(tBinding !=null){
// if there is ArrayType, get the root type
while(tBinding.getComponentType()!=null){
tBinding = tBinding.getComponentType();
}
System.out.println("USING BINDING VARIABLE CLASS IS: " + tBinding.getQualifiedName());
}
}
}
}
My question is: How can I differentiate the variable declarations which can resolve bindings with others which can not?
Many thanks in advance
From the JavaDoc on VariableDeclarationFragment:
Variable declaration fragment AST node
type, used in field declarations,
local variable declarations, and
ForStatement initializers. It
contrast to
SingleVariableDeclaration, fragments
are missing the modifiers and the
type; these are located in the
fragment's parent node.
Try to get the type binding from the VariableDeclarationFragment's parent.

Resources