I want to send a "fact" to a JESS file within java and get the results back. I basicly batch the JESS file and then send my data (structure in here) into the engine by .add(). I tried to get the JESS results, which should be a string, into a "Value".
Rete engine = new Rete();
engine.batch("file.clp");
Value = AAAnull;
try{
engine.add(structure)
AAA = engine.eval("(run)");
} catch ...
System.out.println(AAA);
The result is always a number, although the result should be a string. I have worked it out in a simple java project and the AAA is returning the string, but here it is not working.
The (run) function returns the number of rules fired; that's the number you're seeing here.
The real results of running your program are the side effects it causes; getting the result in Java depends on what side effects you're expecting. That may mean anything from collecting output printed to the screen, finding newly created facts in working memory, or having your Jess program call Java methods that effect the outside world. Without seeing the contents of file.clp I can't say what you're expecting, but all of these things listed are covered in the Jess manual; the phrases above are links to the appropriate sections. I'm happy to answer any followup questions you might have.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I'm trying the retrieve the last modified file name with a matching pattern starts with Order_ and there should not be any hidden files, however it throws compilation error.
try {
File dir = new File("< dir >");
if (!dir.isDirectory()) {
Optional<File> op = Arrays.stream(dir.listFiles(File::isFile))
.max((f1, f2) -> Long.compare(f1.lastModified(), f12lastModified()))
.filter(fl -> fl.getName().startsWith("Order_") && !fl.getCanonicalPath().endsWith("~"))
; // Unhandled exception compilation error for canonicalPath method
}
} catch (Exception e) {
}
Exception: Unhandled exception: java.io.IOException
Any ideas would be greatly appreciated.
This feels like lambda abuse (using a hammer to butter your toast instead of, you know, a butter knife, because you just bought it and it's all shiny and new).
.max() returns either 1, or 0, elements, in the form of an Optional. you then filter that optional to check if the naming is right.
In other words, if the most recently modified file so happens to not start with Order_, this all returns Optional.NONE which surely wasn't your intent. You want to flip your max and your filter line.
More generally, you don't want to do this with lambdas. Inline Lambdas are the lesser evil - they are not exception transparent, not mutable local variable transparent, and not control flow transparent.
These 3 properties are fantastic when a lambda represents code that will run in some other context (e.g. another thread or much later). They are downsides when the code is going to be run then and there.
That means that when a lambda-based strategy and a non-lambda-based strategy for an inline code concept are roughly equally good, then you should prefer the non-lambda-based strategy. This becomes particularly poignant here, as the code is using obsolete API (the old java.io.File API, instead of the newer java.nio.file API).
In this case, .getCanonicalPath() is slightly odd behaviour: The only functional difference between invoking fl.getName().endsWith(...) and fl.getCanonicalPath().endsWith(...) is that the latter will first follow the link if the referenced 'file' is a soft-link.
That sounds like soft-links matter, and if they matter, you don't want this API as it is wonky and ill defined in the face of soft-links. The new API deals with it better, you'd want to use that (java.nio.file.Files's walk method, for example). If soft linking doesn't matter, then it's easy: Replace .getCanonicalPath() with .getName() and all is well. Well, after you fix your bug and flip the filter and max lines back in their right positions.
Note also that .getCanonicalPath() is slow - it needs to hit the disk, or at least, it might. (It will if it is a soft-link; the API doesn't define whether it will in other cases. The JVM impl is free to hit disk on some OSes and not on others. It may run blazingly fast on your system and run dog slow on another, making it hard to test).
I wrote JUnit test for the web service client, which submits JSON document to the service.
I saved "correct" JSON document to the file, then after the test execution I compare it with actual result.
They are not matched, although lines are identical:
org.junit.ComparisonFailure:
Expected :{"Callback":null,"Data":
{"MarketCode":"ISEM",,............"Price":2.99}]}]}]}]}}
Actual :{"Callback":null,"Data":
{"MarketCode":"ISEM",,............"Price":2.99}]}]}]}]}}
Lines are very long , about 4K characters, so I cut much of it here, but their length is identical. I compared string.size() in the debugger , and also I trim it before the compare, to remove some invisible or whitespace symbols in the end, which text editor can implicitly insert.
Also, test is OK when executed isolately. But it fails , when I run it as part of bigger suite.
There is no global/static variables, so memory overriding should be not an issue.
I'm mocking web service client to extract the request string , like this:
StringBuilder pd = new StringBuilder();
doAnswer((invocation) -> {
String postDocument = ((String)invocation.getArguments()[0]).trim();
pd.append(postDocument);
return null;
}).when(client).doPost(anyString(), anyObject());
client is mocked class.
Then I compare trimmed versions of strings, but it doesnt help
String expectedSubmit = TestUtils.readXmlFromFile("strategyexecution\\ireland_bm_strategy_override_expected.json").trim();
assertEquals(expectedSubmit, pd.toString().trim());
I found answer myself :-)
The problem is with JSON specification itself.
JSON cannot guarantee the same order of elements inside the array, it's basically unordered set.
So, the content can be randomly reordered. Two produced JSON files should not be compared as two strings.
I deserialized it to Java object and object comparision works!
Same old issue as we had with XML. For XML there is XMLUnit which semantically compares xml-s. For JSON I'd try to use a similar tool, like JsoNunit. JSONAssert too looks promising.
div(1, sum(1, exp(sum(div(5, product(100, .1)), -5))))
I'm using this in a Solr query, and want to verify that it is the same as :
Where x is 5.
Is this language Java?
If it is, why am I getting this output here:
http://ideone.com/LWYWtU
If it isn't, what language is this and how do I test it?
Thanks in advance for your help.
EDIT: To add more of the surrounding code, here is the full boost value I'm sending to Solr:
if(exists(query({!frange l=0 u=60 v=product(geodist(),0.621371)})),div(1, sum(1, exp(sum(div(product(5), product(100, .1)), -5)))),0)
The reason I think it might be Java is because in the docs, it says Most Java Math functions are now supported, including: and then lists the math functions I ended up using for code.
Solr is Java, but that's not relevant since this is a set of functions that Solr parses and evaluate itself (and not related to Java, except that the backing functions are implemented in Java).
As far as I can say from what you've mapped the functions correctly, as long as the 5 in product(5) is the same as X. You shouldn't need product there, as the value can be included in div directly as far as I can see.
A way to validate it would be to use debugQuery in Solr and see what the value is evaluated as, and then compare it to your own value. Remember that floating point evaluation can introduce a few uncertanities.
I have a very limitied (0) knowledge on AS400 and RPG. But we have a urgent requirement where we need to invoke a RPG program from a java class. So I found that we can achieve it through JTOpen. But I am stuck at declaring the ProgramParameter list. I have the following information about RPG Program
Program name: ZM30000R
Parameters:
Branch 7,0 (Numeric)
Account type 2 (01-cheque,02 savings)
Account Number 20 (character)
Error code 7 (character)
DR/CR indicater 1 (character D,C)
But no clue about what is the intput and output .How to declare the ProgramParameter. I have done as below. I cannot test as well because I dont have connectivity to these systems.
// Create AS400 Text objects for the different lengths
// of parameters you are sending in.
AS400Text branchTxt = new AS400Text(7);
AS400Text accntTypeTxt = new AS400Text(2);
AS400Text accntNumberTxt = new AS400Text(20);
AS400Text errorCodeTxt = new AS400Text(7);
AS400Text DCIndicatorTxt = new AS400Text(1);
// declare and instantiate your parameter list.
ProgramParameter[] parmList = new ProgramParameter[5];
// assign values to your parameters using the AS400Text class to convert to bytes
// the second parameter is an integer which sets the length of your parameter output
parmList[0] = new ProgramParameter( branchTxt.toBytes(branch),7);
parmList[1] = new ProgramParameter( accntTypeTxt.toBytes(accntTypeTxt),2);
parmList[2] = new ProgramParameter( accntNumberTxt.toBytes(accntNumberTxt),20);
parmList[3] = new ProgramParameter( errorCodeTxt.toBytes(""),7);
parmList[4] = new ProgramParameter( DCIndicatorTxt.toBytes(indicator),5);
Any help will be really highly useful.
Thanks and Regards,
Srinivas
Well, I do have a clue just by the description of the parameters. Branch, account type and account number are IN. You need that information for a financial booking or transaction. The error code is appearently OUT. In my experience with financial systems it's reasonable normal that the API returns the way the amount is booked. Normally one would use the sign, but in financial systems the (D)ebit or (C)redit is the better way.
The API is very likely the API of a financial system. If that is true, then I'm missing the amount. Are you sure you've the complete description?
Notice that the first parameter is numeric. You're not in luck. The iSeries and RPG are not very forgiving about the type of a numeric. One can choose from Bit, Zoned, Packed, Decimal, Integer, Float and so on. If the RPG is really RPG instead of ILE RPG, then you can bring that down to Zoned, Packed and Byte.
I assume you've access to the iSeries. Then you can watch the program call, debug information and dump information. That will help you if you have to do "trial and error". If you don't have access, the road will be very hard. You'll receive an error in your java class if the program call is not succesfull. But it will be hard to identify the real error without the information from the iSeries yourself. Therefore, access is really required.
Your sample is mostly on the right track. But your branch parameter is numeric. So you should use AS400ZonedDecimal instead of AS400Text:
AS400ZonedDecimal branchNbr = new AS400ZonedDecimal(7,0)
The RPG program may be expecting packed instead of zoned. No big deal, just use AS400PackedDecimal instead.
As you construct your ProgramParameter object, your constructor requirements are different depending on if they are input or output parameters to your program. For input parameters, just pass the toBytes() results. There is no need to include the length. For output-only parameters, just pass the length.
I agree with Robert's answer that there is some missing information, but his assumptions on the outputness of the error code seems valid. I would guess, however, that the DCIndicator parameter is input since your sample passes a value. For the error code parameter, after your program call, you'll need to extract the value and do something with it. Given what you have already, here is how the program call would work. Take note that I specified a library name of "MyLibrary". That is for example purposes. You will have to determine which library your program object is in.
ProgramCall pgm = new ProgramCall(as400, QSYSObjectPathName.toPath("MyLibrary","ZM30000R","PGM"), parmList);
if (pgm.run() == true) {
String sErrorCode = (String) errorCodeTxt.toObject(parmList[3].getOutputData());
//Do something with your output data.
}
else {
AS400Message[] messageList = pgm.getMessageList();
for (int i=0; i<messageList.length; i++) {
String sMessageID = messageList[i].getID();
String sMessageText = messageList[i].getText();
//Do something with the error messages
}
}
Something else to consider is library lists. Does the RPG program expect certain libraries to be in the library list? If so, you should issue CommandCalls to add the libraries to the library list before calling the program.
FWIW: It's a lot easier to call IBM i host programs & service programs using PCML rather than ProgramCall.
The compilers will even generate the PCML document for you.
See http://javadoc.midrange.com/jtopen/com/ibm/as400/data/ProgramCallDocument.html for details.
If you don't have connectivity, then you really can't do what is asked. How do you test it? Is there numeric parameters or are they all character?
I have a question which is described below:
What problems would arise for testing a Java class which counts number of words in a file?
The function's signature is below:
public int wordCount(String filename)
Well, this is a junit testing question.
If you know the problem, what is the solution of that?
So your question is what to test for? If yes, I'd say you should check if the definition of "word" is implemented correctly (e.g. is "stack-overflow" one word or two), are new lines handled correctly, are numbers counted as words (e.g. difference between "8" and "eight"), are (groups of special) characters (e.g. a hyphen) counted correctly.
Additionally, you should test whether the method returns the expected value (or exception) if the file does not exist.
This should be a good starting point.
To sfussenegger's list, I'd add the file handling checks: does the method respond correctly to files not found (including null filename), or lacking read permission?
Also, to sfussenegger's correctness list, I'd add whether duplicates count and case sensitivity rules, as well.
Of course, all of this requires that you know how the method is supposed to behave for all of these specifics. It's easy to tell someone to "go count words", but there are subtleties to that assignment.
Which is one of the big benefits of writing a good set of unit tests.
This really sounds like a task for FIT: Framework for Integrated Test. It's an acceptance testing framework that works with ant and JUnit.
One docent of mine did such a task and used this framework. It allows you to write a whole bunch of test cases within one html/wiki table. FIT will interpret each line as a parameter set for the function under test and checks the output.
For example:
This table displays the result of three test cases. Two passed, one failed.
You can use fit if you write sentences and define the number of words in your table. With FIT, they're executed and the result is displayed in a new table.
For further information, please read Introduction to FIT.