Perl: how to validate successful call to "XML::eXistDB::RPC" - perl

i am writing a small perl app using the eXist database, and i am wondering is:
how can i see that my call
my $eXist = XML::eXistDB::RPC->new( destination=>$eXist_db, repository=>$bank, user=>"admin", password=>"pass" ) ;
is successful or not ?
thanx

When object initialisation fails, it will be messaged through Log::Report, so hook into that.
This only happens if the programmer to neglected to set either rpc or destination parameter. The new constructor will always return an object instance.

According to the docs:
All methods return a LIST, where the
first scalar is a return code (RC).
When that code is 0, all went well.
Otherwise, the code represent the
transport error or the exception
(refusal) as reported by the server
logic. In either case, the second
scalar in the returned list contains
the error message. For instance,
Maybe this applies also for the constructor, try:
my ($rc,$eXist) = XML::eXistDB::RPC->new( destination=>$eXist_db, repository=>$bank, user=>"admin", password=>"pass" );
now, if $rc != 0 there was an error.

Related

How to check if Archive::Tar's write is successful?

I have a monthly Script running to archive files from past month. I'm using Archive::Tar to generate the archive. How can I check if calls to the ->write method are successful?
Does the following work? I didn't manage to fail $tar->write() yet.
unless ($tar->write( $name . '.tar.xz', COMPRESS_XZ )) {
die("cant write tar"); # or any other doings instead
}
Yes, the code in your question will catch any error within ->write.
The documentation of Archive::Tar does not specify what the return value of write is (except when no argument is provided, which isn't the case here). However, looking at the code of the module, write returns undef in case of an error and a true value in case of success:
1 if it was writing to a file (this is the case for the code in your question)
the written string if it was writing in a string.
Note that if something goes wrong and Archive::Tar returns undef, then it will also print an error message (unless you set $Archive::Tar::WARN to 0 by doing $Archive::Tar::WARN = 0). If you want to do something specific depending on the error, you can access the error message using the ->error method.

perl6 Changes in IO::Socket::INET from last year and broken promises

When I asked a question last year about promises, my echo server was working (see this link: perl6 how to get specific identity of promises? ). However, with the new versions of perl6, my echo server is no longer working.
I guess I can try the example from the perl6 documentation site ( https://docs.perl6.org/type/IO::Socket::INET ), but I want to find out what mistake I have made in my code. My current level has precluded me from seeing the difference between my codes and the codes on the perl6 documentation site. Please give me a hint; thanks !
my #result;
for 0 .. 2 -> $index {
#result[$index] = start {
my $myPromiseID = $index;
say "======> $myPromiseID\n";
my $rsSocket = IO::Socket::INET.new:
localhost => 'localhost',
localport => 1234 + $index,
listen => 1;
while $rsSocket.accept -> $rsConnection {
say "Promise $myPromiseID accepted connection";
while $rsConnection.recv -> $stuff {
say "Promise $myPromiseID Echoing $stuff";
$rsConnection.print($stuff);
}
$rsConnection.close;
}
}
}
await #result;
And the error messages are:
Tried to get the result of a broken Promise
in block <unit> at p6EchoMulti.pl line 24
Original exception:
Nothing given for new socket to connect or bind to
in block at p6EchoMulti.pl line 8
Actually thrown at:
in block at p6EchoMulti.pl line 13
This commit, which was announced in the Jan 2017 section of Rakudo's changelog as "Fixed bug where IPv6 URIs were not parsed correctly" did a lot more that just fix a URI parsing bug. It also completely redid the parameter binding/validation of an IO::Socket::INET.new call, and one consequence is it broke your code because the updated code requires that listen be an actual Bool, not merely coerce to one.
The old code (the code on the left of the commit link above) had a simple method new (*%args is copy). This matched your call. The error (fail "Nothing given for new socket to connect or bind to") did not trigger because 1 evaluates to True in a boolean context so %args<host> || %args<listen> was also True. So the rest of the code ran with listen set to 1 and it all worked out fine.
Rakudos from 2017.01 have the code on the right at the commit link above. Note how there are now multiple new methods (i.e. multiple multi method new ... declarations).
The multi(s) intended to handle a call that specifies a listen argument is/are of the form multi method new (..., Bool:D :$listen!, ...). Note the Bool:D.
A call to new, with the listen parameter set to True, matches this multi and works as expected.
But a call with :listen(1) will just match the generic multi method new (*%args) signature instead. This latter does an unconditional fail "Nothing given for new socket to connect or bind to";.
Okay, after some struggling, it seems to have improved if I changed listen=>1 to listen=>True.
Can anyone care to explain why 1 was not evaluated to True, and why it worked before?
Thanks.

Perl error: use of uninitialized value $DBI::err in concatenation

I wrote a procedure which imports data from an xml-file into a MariaDB using library DBI. The procedure works but I don't understand why the following code gives me the message:
use of uninitialized value $DBI::err in concatenation (.) or string at ...
Here the code (abbreviated):
my $insert_art = $dbh->prepare(
"INSERT INTO odbb_articles (creation_dt,ref_data,comp_no)".
"VALUES (?,?,?)"
);
....
my $comp_no = $xpc->findvalue('./sr:ARTCOMP/sr:COMPNO',$node1);
....
$insert_art->execute($creation_dt,$ref_data,$comp_no)
or die "Fehler bei der Ausfuehrung: ".
"$DBI::err -> $DBI::errstr (odbb_articles $DBI::state)\n";
If I insert the code
if ($comp_no eq "") { $comp_no = undef; }
just before $insert_art->execute the procedure works. This error happens when there is no entry in the xml-file for element COMPNO. I can avoid it if I define it as undef. I just wonder
why $comp_no cause this problem and
is there another solution than to control if $comp_no is "" and define it as undef?
The reason for the second question is to avoid the if statement if there are a lot of variables/columns which may have empty entries.
Thanks for help.
use of uninitialized value $DBI::err in concatenation (.) or string at ...
The error message you are seeing is Perl telling you that $DBI::err is undef. That is not because of the value of your $comp_no. It's just a result of what your program is doing.
So when you pass an empty string to the comp_no column, the database doesn't like that. It throws an error. DBI catches that error and passes it on. The $insert_art->execute returns a false value and the right-hand-side of the or gets called. That's your die.
Now in the string that you pass to die you put three variables:
$DBI::err
$DBI::errstr
$DBI::state
According to the DBI documentation, those are equivalent to the functions $h->err, $h->errstr and $h->state with $h being the last handle used. Let's look at the docs for those.
$h->err
Returns the native database engine error code from the last driver method called. The code is typically an integer but you should not assume that.
The DBI resets $h->err to undef before almost all DBI method calls, so the value only has a short lifespan. Also, for most drivers, the statement handles share the same error variable as the parent database handle, so calling a method on one handle may reset the error on the related handles. [...]
This does not explain when it can be undef.
$h->errstr
Returns the native database engine error message from the last DBI method called. This has the same lifespan issues as the "err" method described above.
The returned string may contain multiple messages separated by newline characters.
The errstr() method should not be used to test for errors, use err() for that, because drivers may return 'success with information' or warning messages via errstr() for methods that have not 'failed'.
Ok, so this is text. Don't use it to test for specific errors. You're not doing that. You just want to give debug output when the program fails.
$h->state
Returns a state code in the standard SQLSTATE five character format. Note that the specific success code 00000 is translated to any empty string (false). If the driver does not support SQLSTATE (and most don't), then state() will return S1000 (General Error) for all errors.
The driver is free to return any value via state, e.g., warning codes, even if it has not declared an error by returning a true value via the "err" method described above.
The state() method should not be used to test for errors, use err() for that, because drivers may return a 'success with information' or warning state code via state() for methods that have not 'failed'.
Again, this is not very clear about how useful it is.
My advice is to get rid of $DBI::err and $DBI::state. You don't need those to figure out what the problem is. Just output $DBI::errstr.
$insert_art->execute($creation_dt,$ref_data,$comp_no)
or die "Fehler bei der Ausfuehrung: " . $dbh->errstr;
Now your program will still fail, but at least you will have a meaningful error message that will explain what your database didn't like about the statement. That's better than being told how there is a bug in your error handling code.
Afterwards, the other answers will probably apply to fix the reason this is happening in the first case.
On another note, a word on die: If you provide a \n at the end of your arguments, it will not print your current script, line number and input handle line number. But those might be useful in your case. You can include them.
In a SQL database an empty string is very different to null.
If comp_no has a foreign key pointing to a record in another table, then the value "" is an accettable one only if there is a record with "" as primary key, very improbable.
Yu can fix this converting empty values to undef:
for ($creation_dt,$ref_data,$comp_no ){
defined $_ and $_ eq '' and $_ = undef;
}
$insert_art->execute($creation_dt,$ref_data,$comp_no);
or also
$insert_art->execute(map {defined($_) && length($_) ? $_ : undef} ($creation_dt,$ref_data,$comp_no));
This is a possible shortcut:
$comp_no ||= undef;
With the caveat that this will work in any case where $comp_no evaluates as false, meaning a value of 0 will actually cause the result to go undef also, which may or may not matter to you. If your field is numeric, I'd say it matters a lot.

Call to a member function on a non-object error symfony2

This is an odd one. I have this method, that is the callback for the FormEvents::POST_SET_DATA event in an EventSubscriber of a form in Symfony2:
public function preSetData(FormEvent $event)
{
$data = $event->getData();
$form = $event->getForm();
$resource_provider = $data->getResourceProvider();
$type = $resource_provider->getType(); //PROBLEM HERE
\Doctrine\Common\Util\Debug::dump(is_object($resource_provider));
}
It has more code but the error is firing in the line with the comment PROBLEM HERE.
The issue is that the dump there prints bool(true), so it is an object, and have the data inside, but trying to call getType(), that exist, fails with this error:
Error: Call to a member function getType() on a non-object
To add more confusion, if I dump $resource_provider->getType() I get the expected content dumped, but the error remains.
Does someone knows or has a clue on what can be happening here?
EDIT
Can't believe it! I found the answer, but doesn't makes sense at all! I had to wrap the problematic code with a conditional like this:
if(is_a($resource_provider, 'My\Bundle\Path\Entity\ResourceProvider')){}
and it worked! If someone can tell me what is the sense of that, I will happily select his/her answer as correct.
The problem is that $resource_provider is probably null as error says $resource_provider is not an object.
When printing the value of $resource_provider and skipping the script, it shows the right object of class 'My\Bundle\Path\Entity\ResourceProvider' :
echo get_class($resource_provider); exit; // Display My\Bundle\Path\Entity\ResourceProvider and skip the script
When adding a condition to test is the object is of the expected class, the script doesn't crash anymore :
if(is_a($resource_provider, 'My\Bundle\Path\Entity\ResourceProvider')){}
In addition, when skipping script when it's not an object, $resource_provider is null and the script skipped :
if(is_a($resource_provider, 'My\Bundle\Path\Entity\ResourceProvider')){
} else {
var_dump($resource_provider); exit;
}
$resource_provider is an object and null in the same "execution" of the script.
So we can deduce that the EventSubcriber is loaded more than one time, perhaps before the form binding and after form binding for example and the first time with the expected object, and a second (or more) time with no value, as null, perhaps because the $resource_provider is not filled when submitting form or something else.

JUnit4: assumeThat message is not printing

How can I see the error messages of assumeThat in JUnit4?
This test passes but does not print anything. The reason is that to perform the test on read1, I require b to be true. Since b is false, the test does not apply.
boolean b = false;
byte[] read1 = null;
assumeThat("b shold be true to continue testing", b, is(true));
assertThat("read1 should not be null", read1, is(notNullValue()));
I have not found any kind of log with the assumeThat messages. My issue here is that I would like to know which tests passed but did not completed because assumption X failed. It would be nice if a message (for example similar to when an assertion fails) was still printed for the assumptions.
Strangely as it may seem, I haven't been able to find comments on this problem (including in the JUnit page). So there is a chance that I'm just doing something wrong or looking for messages in the wrong place. I'm using Eclipe.
If I understand you correctly, the
assertThat("read1 should not be null", read1, is(notNullValue()));
should only be executed if b == true, but it's not an error if b == false?
Then why don't you simply do:
if(b) {
assertThat("read1 should not be null", read1, is(notNullValue()));
} else {
log.warn("b == false, Test on read1 skipped");
}
? Or do you want to have a special test result state ("success-but-suspicious") if that happens?
Update: I just re-read the docs on Assume. It states that if an assumtion fails, the entire test is considered "not meaningful" and marked as "ignored". With small, focused tests that should usually give you all the info you need.
Update2: Just tried it with the JUnit 4.8 in Eclipse 4.2 I have on hand here. That just marks the test as successful. So I guess the JUnit runner in Eclipse might not support that feature correctly.
An error isn't printed because an assumption failure isn't an error. The assume methods are used to short-circuit tests that should not be run due to the value or state one or more objects (or primitives). Assumptions were designed for the Theories runner but they can be used in other runners as well.
One common usage of assumptions is when you have multiple test methods that need to perform some set of operations to get an object into a particular state before the actual test case logic can be performed.
Before assumptions, each test would get the object into a desired state, assert that it is in that state, then continue. For example, for a test of a stack, many tests require a non-empty stack, so you would create a stack, push an item, assert the stack is not empty, then do the rest of the test (pop an item, push another item, etc).
The problem comes if you do this pattern in multiple tests, and then a bug gets introduced that causes all of these tests to fail (for example, isEmpty() always returning true). When you run the tests you get so many failures that you don't know where to start.
So instead you have one test that verifies that if you push an item into an empty stack, isEmpy() returns false. Then any test that needs a non-empty stack does this:
Stack<Object> stack = new Stack<>();
stack.push(new Object());
assumeFalse(stack.isEmpty());
// Continue with the test methods
If you want an error message, you probably want to use an assertion.
Agreeing with the previous answer (by NamshubWriter).
However, if you really want (justifiably) to have a clear indication that the test was ignored because some assumption failed, you can do something like:
#Before
public void before() {
final String mandatoryPropKey = "system.mandatory-property-for-this-test";
final String mandatoryPropExpectedVal = "true";
try { // try/catch because the Assume failure won't print any message (by design)
Assume.assumeTrue("Assumed that the \"" + mandatoryPropKey + "\" system property is \"" + mandatoryPropExpectedVal + "\".", Boolean.valueOf(System.getProperty(mandatoryPropKey, mandatoryPropExpectedVal)));
} catch (AssumptionViolatedException ave) {
logger.warn("Not executing this test because this assumption failed: {}", ave.getMessage());
throw ave;
}
}