I have the following problem. I want to execute a policy that checks for existance of a node and after that it should check if the value is greater than 0.
So lets say we have "xmlDoc" and I want to check if the node "test" exists and if the value of "test" is greater than 0.
<xmlDoc>
<test>5</test>
</xmlDoc>
When the node exists, there is no problem. When the node is missing though, all hell breaks lose..
It is obvious why he crashes. He can't find the node "test" so he can't check its value.
My question: is it possible in the BizTalk BRE to check on existance and on value of a node without it crashes?
There is the 'exists' Predicate on the list of Conditions, however, this doesn't always work since value fact is also evaluated.
One way I've found to address this is by creating a Vocabulary item and adjusting the Selector to point to the Element that may not exist, "text" in your case.
Then the XPath field would be the /text() node.
This way, if the Selector path returns null, the BRE knows the fact doesn't exist so no Rule that requires it will be evaluated.
If not exist check is performed alongwith value check, BRE does not work as expected.
Solution :
Below function will return node value and empty string if node does not exist.
Use return value of this function to perform value check.
claim : XML document.
path : XML path.
public static string GetXMLPathValue(TypedXmlDocument claim, string path)
{
string nodeContent = string.Empty;
if (claim.Document.SelectSingleNode(path) != null)
return claim.Document.SelectSingleNode(path).InnerXml;
return nodeContent;
}
Related
I have some code and when I run it produces an error, saying:
NoSuchMethod: the method 'XYZ' was called on null
What does that mean and how do I fix it?
Why do I get this error?
Example
As a real world comparison, what just happened is this conversation:
Hey, how much gas is left in the tank of the car?
What are you talking about, we don't have a car.
That is exactly what is happening in your program. You wanted to call a function like _car.getGasLevel(); but there is no car, the variable _car is null.
Obviously, in your program it might not be a car. It could be a list or a string or anything else really.
Technical explanation
You are trying to use a variable that is null. Either you have explicitly set it to null, or you just never set it at all, the default value is null.
Like any variable, it can be passed into other functions. The place where you get the error might not be the source. You will have to follow the leads from the actual null value to where it originally came from, to find what the problem is and what the solution might be.
null can have different meanings: variables not set to another value will be null, but sometimes null values are used by programmers intentionally to signal that there is no value. Databases have nullable fields, JSON has missing values. Missing information may indeed be the information itself. The variable bool userWantsPizzaForDinner; for example might be used for true when the user said yes, false when the user declined and it might still be null when the user has not yet picked something. That's not a mistake, it's intentionally used and needs to be handled accordingly.
How do I fix it?
Find it
Use the stack trace that came with the error message to find out exactly which line the error was on. Then set a breakpoint on that line. When the program hits the breakpoint, inspect all the values of the variables. One of them is null, find out which one.
Fix it
Once you know which variable it is, find out how it ended up being null. Where did it come from? Was the value never set in the first place? Was the value another variable? How did that variable got it's value. It's like a line of breadcrumbs you can follow until you arrive at a point where you find that some variable was never set, or maybe you arrive at a point where you find that a variable was intentionally set to null. If it was unintentional, just fix it. Set it to the value you want it to have. If it was intentional, then you need to handle it further down in the program. Maybe you need another if to do something special for this case. If in doubt, you can ask the person that intentionally set it to null what they wanted to achieve.
simply the variable/function you are trying to access from the class does not exist
someClass.xyz();
above will give the error
NoSuchMethod: the method 'xyz' was called on null
because the class someClass does not exist
The following will work fine
// SomeClass created
// SomeClass has a function xyz
class SomeClass {
SomeClass();
void xyz() {
print('xyz');
}
}
void main() {
// create an instance of the class
final someClass = SomeClass();
// access the xyz function
someClass.xyz();
}
val args = Bundle()
args.putString("type", details.type)
navigator.navigate(context!!, findNavController(), Destination.TYPE, args)
I am quite confused as to why in the receiving fragment when I go to access the arguments I have passed through it is responding with...
val type: String = arguments.getString("type")
The arguments.getString is all underlined red and says "Required String Found String?" But how when I called method "putString"?!?
It is resulting in text not being rendered in the new fragment and I assume this is a nullability issue.
It's a matter of knowledge that is available in the receiving Fragment.
The Fragment is not aware of how its arguments were created (or modified) so it has to assume the "type" key you're looking for might not be in the arguments Bundle. That's why it returns a nullable (String?) result (the null value would mean absent in arguments).
Your fragment might be created in many places in your app and its arguments might have been modified in many places. We have no way of tracking that.
There are different solutions for this problem, depending on your approach in other parts of the code and how "confident" you are in creating of your Fragment.
I would usually choose a solution in which I assume setting the type is mandatory. Therefore if the type is absent - I fail fast. That would mean the Fragment was misused.
val type: String = arguments!!.getString("type")!!
The code above will crash if either:
a) arguments weren't set, or
b) String with type wasn't put in the arguments Bundle.
You are right, that is a : null ability issue.
First you should be sure if you are expecting a value, so try adding "?" or "!!", i would recommend "?", or go with the block of if {} else
To read the string safely you can use:
val type: String = arguments?.getString("type").orEmpty()
The orEmpty call at the end ensures that a valid String is returned even if either arguments or getString() returns null.
The method signature for getString() returns a nullable String. This is because at compile time, the compiler can't know if the value exists in the bundle or not. You will have the same issue when retrieving anything from any Map.
If you know for certain that the value in the bundle or map should exist at the time you call getString(), you can use the !! operator. That's what it's there for. When you know something should always be there, it is appropriate to want an exception to be thrown (in this case KNPE) if it's not there so you can easily find any programming error during testing.
isEmpty() or ?.let aren't helpful in this particular case because they would just be masking a programming error and making it harder to discover or debug.
How to read value for the given key from a map, with providing a default value (used if the map doesn't contain entry for the specified key),
but without updating the map - this is what get method does:
get(Object key, Object defaultValue)
Looks up an item in a Map for the given key and returns the value - unless there is no entry for the
given key in which case add the default value to the map and return
that.
Ofc it must be a single, short expression
For performance reasons, creating a deepcopy on that map (so it could be updated) and using mentioned get is not a solution.
Equivalents in different languages:
JavaScript: map["someKey"] || "defaultValue"
Scala: map.getOrElse("someKey", "defaultValue")
Python3: map.get("someKey", "defaultValue")
Use Java's getOrDefault Map method (since Java 8):
map.getOrDefault("someKey", "defaultValue")
it will not add new key to the map.
Given the examples you gave for some other languages and your expressed requirement to not update the Map, maybe you are looking for something like this...
map.someKey ?: 'default value'
Note that with that, if someKey does exist but the value in the Map associated with that key is null, or zero, false, or anything that evaluates to false per Groovy truth rules, then the default value will be returned, which may or may not be what you want.
An approach that is more verbose might be something like this...
map.containsKey('someKey') ? map.someKey : 'default value'
I have a specification of a function that acts like a constructor. The specification of the function is
function Create_Controller return Type_Controller;
Also, in the specification file, I have the Type_Controller type, which is an access. I copy the relevant fragment:
type Type_Controller_Implementation;
type Type_Controller is access Type_Controller_Implementation;
So, this is what I've attempted:
function Create_Controller return Type_Controller
is
My_Controller : aliased Type_Controller_Implementation;
begin
return My_Controller'Access;
end Create_Controller;
I tried to compile the program without the aliased keyword, but then, the compiler says:
prefix of "Access" attribute must be aliased
So, I put the aliased keyword and the compiler now suggests that I should change the specification:
result must be general access type
add "all" to type "Controlador_De_Impresion" defined at controller.ads
The problem is that I'm not allowed to change the specification. I've read the chapter about access types in the Ada Programming Wikibook, but I still don't understand why my code doesn't work. What am I doing wrong?
The implementation of the Create_Controller function body is incorrect. Were it to work as coded, you'd be returning a pointer to a variable local to that function body's scope...which would be immediately lost upon returning from the function, leaving you with an invalid pointer.
No, an instance of the type needs to be allocated and returned. If there's no explicit initialization that needs to occur you can simply do:
return new Type_Controller_Implementation;
If there is some initialization/construction that has to occur, then:
function Create_Controller return Type_Controller
is
My_Controller : Type_Controller := new Type_Controller_Implementation;
begin
-- Set fields of My_Controller
...
return My_Controller;
end Create_Controller;
When you declare an access type as access T, you're saying that "this is a pointer to a T and it must point to objects of type T allocated from a pool". (That is, allocated with a new keyword.) When you declare an access type as access all T, you're saying that it can point either to a T allocated from a pool, or to an aliased variable of type T.
If the type is declared as access T and you can't change it, then all access values of the type have to point to something allocated with new. You can't make it point to a variable (even to a "global" variable that isn't located on the stack).
The reasons for this are historical, I think. The first version of Ada (Ada 83) only had "pool-specific types." You couldn't make an access value point to some other variable at all, without trickery. This meant that a compiler could implement access values as indexes into some storage block, or as some other value, instead of making them the actual address of an object. This could save space (an access value could be smaller than an address) or allow more flexibility in how pool memory was managed. Allowing access values to point directly to objects takes away some of that flexibility. I think that's why they decided to keep the old meaning, for backward compatibility, and require an all keyword to indicate the new kind of access.
From the doc
Add(CacheItem, CacheItemPolicy) : When overridden in a derived class, tries to insert a cache entry into the cache as a CacheItem instance, and adds details about how the entry should be evicted. [1]
-
Set(CacheItem, CacheItemPolicy) : When overridden in a derived class, inserts the cache entry into the cache as a CacheItem instance, specifying information about how the entry will be evicted. [2]
I see little difference in the wording (tries to) and signature (set is a sub, add returns a boolean), but I'm not sure which one I should use and if there is really something different between both.
The Main difference is that the Add() method tries to insert a cache without overwriting an existing cache entry with the same key.
While the Set() method will overwrite an existing cache entry having the same key. [ However If the key for an item does not exist, insertion will be done as a new cache entry ].
Above was the difference in terms of their functionality.
Syntactical Difference:
One significant syntactical difference is that the Add() method returns a Boolean which is true if insertion succeeded, or false if there is already an entry in the cache that has the same key as item.
The Set() method has a void return type.
One last point that internal implementation of Add() method actually calls its corresponding version of AddOrGetExisting() method.
public virtual bool Add(CacheItem item, CacheItemPolicy policy)
{
return this.AddOrGetExisting(item, policy) == null;
}