-
Notifications
You must be signed in to change notification settings - Fork 115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue446: Bean accessors don't account for IndexedPropertyDescriptors #449
Changes from 1 commit
4bd9490
b41ffee
27e120f
2d81c3e
1a12065
dc754f9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,7 +31,8 @@ | |
Accumulator | ||
ISystemFact] | ||
[java.beans | ||
PropertyDescriptor] | ||
PropertyDescriptor | ||
IndexedPropertyDescriptor] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This new import does not seem like it is needed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cleaned up: |
||
[clojure.lang | ||
IFn])) | ||
|
||
|
@@ -179,10 +180,13 @@ | |
;; Iterate through the bean properties, returning tuples and the corresponding methods. | ||
(for [^PropertyDescriptor property (seq (.. java.beans.Introspector | ||
(getBeanInfo cls) | ||
(getPropertyDescriptors)))] | ||
|
||
[(symbol (string/replace (.. property (getName)) #"_" "-")) ; Replace underscore with idiomatic dash. | ||
(symbol (str "." (.. property (getReadMethod) (getName))))]))) | ||
(getPropertyDescriptors))) | ||
:let [read-method (.getReadMethod property)] | ||
;; In the event that there the class has an indexed property without a basic accessor we will simply skip | ||
;; the accessor as we will not know how to retrieve the value. see https://github.com/cerner/clara-rules/issues/446 | ||
:when read-method] | ||
[(symbol (string/replace (.getName property) #"_" "-")) ; Replace underscore with idiomatic dash. | ||
(symbol (str "." (.getName read-method)))]))) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You'll want to be careful that nothing here adds new reflection. Perhaps compile a session (thus doing evals) with reflection warnings turned on. This would be a good test to have actually though perhaps a bit out of scope here; as far as I know we don't have a test for this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adding
to the project and building doesn't show this as a reflection.
So, i think we are good for this example. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, doesn't look like reflection. I think we should just have :global-vars {*warn-on-reflection* true} at the top-level of our lein project.clj though in general There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why not: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To be clear, my concern wasn't necessarily with reflection warnings in Clara itself but rather with reflection when invoking accessors on Java objects. For example:
reflecting when invoking the .getA method behind the scenes. However in any case if that were happening I'd expect to see more warnings in the Travis build with global reflection warnings enabled - in particular, warnings interspersed through test execution when eval calls build rule networks. So +1. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, yeah that makes sense. I believe the reason that the rules network fns don't experience reflection is because we add the metadata a bit later: |
||
|
||
(defn effective-type [type] | ||
(if (compiling-cljs?) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package clara.test.facts; | ||
|
||
/** | ||
* A Java Pojo for the express purpose of testing the behavior of compilation and execution of rules. | ||
* | ||
* This class should not be included in the released artifact, if it did make it into a released artifact it should be | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why can't it be under There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, I don't understand why this needs to be in the main source path and then removed from the jar afterward rather than just put in a test source path from the start. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My lein is not that strong, but yeah that works: |
||
* ignored and not consumed as it may be moved/removed without warning to consumers. | ||
*/ | ||
public class BeanTestFact { | ||
private String[] locations; | ||
private String[] roadConditions; | ||
|
||
public BeanTestFact(String[] locations) { | ||
this.locations = locations; | ||
} | ||
|
||
// Standard and Indexed property accessors | ||
public void setLocations(String[] locations) { | ||
this.locations = locations; | ||
} | ||
public String[] getLocations() { | ||
return locations; | ||
} | ||
public void setLocations(int pos, String location) { | ||
locations[pos] = location; | ||
} | ||
public String getLocations(int pos){ | ||
return locations[pos]; | ||
} | ||
|
||
// Partial Indexed property accessor, ie. no standard accessor | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps add the issue link to this comment as well. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 |
||
public void setRoadConditions(int pos, String condition) { | ||
roadConditions[pos] = condition; | ||
} | ||
public String getRoadConditions(int pos){ | ||
return roadConditions[pos]; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
(ns clara.test-java-facts | ||
(:require [clara.tools.testing-utils :as tu] | ||
[clara.rules :as rules] | ||
[clojure.test :refer [is deftest run-tests testing use-fixtures]]) | ||
(:import [clara.test.facts | ||
BeanTestFact])) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test seems like it could go in the test_java namespace as well, but I don't have strong feelings about it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was on the fence about that, I kind of felt like the test_java namespace was testing the Java apis rather than the usage of java roots in the rulebase and thats why i created a new namespace. |
||
;; A test to demonstrate that a Pojo with indexed property accessors can be used as an alpha root in a session, | ||
;; see https://github.com/cerner/clara-rules/issues/446 | ||
(tu/def-rules-test test-basic-rule | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that using def-rules-test isn't really needed here since this presumably isn't going to be tested in ClojureScript, but it doesn't do any harm. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did this for consistency There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might as well test all that we can test on all platforms. |
||
{:rules [kansas-rule [[[BeanTestFact | ||
(= ?locs locations) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So would direct field access on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's what I'd think yes. A test that an actual invocation of the indexed accessor in a rule for the property without a standard accessor still works might be nice to have and wouldn't be hard to create but isn't crucial. I realize it should still pass with this implementation, I just tend to prefer having tests be implementation agnostic where possible. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added a test demonstrating that a compilation error is thrown when trying to use the standard accessor: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 |
||
(some #(= "Kansas" %) ?locs)]] | ||
(rules/insert! "Kansas Exists")]] | ||
:queries [string-query [[] [[?s <- String]]]] | ||
|
||
:sessions [empty-session [kansas-rule string-query] {}]} | ||
|
||
(let [locs (make-array String 2)] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 |
||
(aset locs 0 "Florida") | ||
(aset locs 1 "Kansas") | ||
(let [session-strings (into #{} | ||
(map :?s) | ||
(-> empty-session | ||
(rules/insert (BeanTestFact. locs)) | ||
(rules/fire-rules) | ||
(rules/query string-query)))] | ||
(is (= 1 (count session-strings))) | ||
(is (contains? session-strings "Kansas Exists"))))) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A slightly more concise option:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. updated: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They really shouldn't even be in the "main" src path, but that's a topic for another build related issue I think.
Any reason this was added in this particular PR though?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed with:
b41ffee