-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
HHH-18106 - @CheckHQL is reporting error when named query contains valid Java constant #8374
HHH-18106 - @CheckHQL is reporting error when named query contains valid Java constant #8374
Conversation
577f1c9
to
bdd6e10
Compare
Thanks for your pull request! This pull request appears to follow the contribution rules. › This message was automatically generated. |
bdd6e10
to
0080bcf
Compare
import static org.junit.jupiter.api.Assertions.assertNotNull; | ||
|
||
@TestForIssue(jiraKey = "HHH-No-Such-Key") | ||
public class ConstantInNamedQueryTest { |
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.
Currently we're testing the query validation just as an integrated part of the code generation, with tests in /tooling/metamodel-generator/src/test/java
. This isn't perfect by a long shot, but it's good enough until we sit down and come up with something much better. And, yes, It's true that it doesn't exercise @CheckHQL
, but that annotation is essentially trivial.
I'm not at all a fan of the approach you're proposing here. This test is verbose and is going to be difficult to understand and maintain. I would prefer if you just follow the existing (admittedly imperfect) approach.
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.
I absolutely agree that this test is more than ugly. I will be more than happy if I will be able to test it in the same way as the other tests. But the problem is that existing CompilationTest's are being executed with inherited class path. This results in all used classes to be present in class loader in BasicDotIdentifierConsumer.resolvePath. This way problem will never be visible in tests, but it will be still present in standalone example. That is the only reason why I've created such an ugly test case.
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.
Not sure what you mean.
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.
Sorry if my explanation is (little bit) messy :-(
The point is that, when processor if running standalone, class loader does know anything about classes that is processing. When BasicDotIdentifierConsumer.resolvePath
is trying to resolve class using ClassLoaderService, ClassNotFoundException is thrown, caught and ignored, then next statement is throwing SemanticExpression with message "Could not interpret expression ...". Which is correct outcome when non existing class is referenced.
If testing is done with existing approach (test class that extends CompilationTest
) ClassLoaderService already knows all classes under src/test/java, BasicDotIdentifierConsumer.resolvePath
can find referenced class, and everything works like there is no problem present.
Below is simple test class that will pass. Normally, first two assertions should pass, but third and fourth not.
public class ConstantInNamedQueryTestv2 extends CompilationTest {
@Test
@WithClasses({ CookBook.class })
public void testCase() {
assertPresenceOfFieldInMetamodelFor( CookBookWithCheck.class, "QUERY_FIND_BAD_BOOKS" );
assertPresenceOfFieldInMetamodelFor( CookBookWithCheck.class, "QUERY_FIND_GOOD_BOOKS" );
assertPresenceOfMethodInMetamodelFor( CookBookWithCheck.class, "findBadBooks", EntityManager.class );
assertPresenceOfMethodInMetamodelFor( CookBookWithCheck.class, "findGoodBooks", EntityManager.class );
}
}
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.
If testing is done with existing approach (test class that extends CompilationTest) ClassLoaderService already knows all classes under src/test/java
That's weird and surely wrong. We must have something set up wrong.
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.
OK, then I will check to see if there is some problem with current approach to testing. My assumption was that this is working as expected, so I've created all this "mess" to work differently.
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.
Awesome, thanks!
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.
Every source file under tooling/metamodel-generator/src/main/java
will be compiled and .class visible to class loader. Those that must not be visible should be placed elsewhere. Most logical place is tooling/metamodel-generator/src/main/resources
.
Possible solutions to isolate some of sources used for testing are either to add new parameter to WithClasses
annotation or to create new annotation (like existing WithMappingFiles
or WithProcessorOption
). I've implemented first option, but this can be easily changed.
The thing that I do not like in this draft solution is that I had to duplicate several methods (and only those needed for testing in this particular case) in org.hibernate.processor.test.util.TestUtil
to accept class name instead of class itself.
Of two test methods in test class, one is accepting only one source which is placed in resources directory, and other where entity class is in sources directory, but class containing constants is in resources.
0080bcf
to
2214901
Compare
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.
LGTM, thanks so much for this!
return e.getKind() == ElementKind.FIELD && | ||
e.getModifiers().contains( Modifier.STATIC ) && | ||
e.getModifiers().contains( Modifier.FINAL ); |
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.
return e.getKind() == ElementKind.FIELD && | |
e.getModifiers().contains( Modifier.STATIC ) && | |
e.getModifiers().contains( Modifier.FINAL ); | |
return e.getKind() == ElementKind.FIELD | |
&& e.getModifiers().contains( Modifier.STATIC ) | |
&& e.getModifiers().contains( Modifier.FINAL ); |
@Override | ||
public JavaType<?> getJavaConstantType(String className, String fieldName) { | ||
final Class<?> fieldType = javaConstantType( className, fieldName ); | ||
return getTypeConfiguration() |
Check warning
Code scanning / CodeQL
Subtle call to inherited method
c78c0e1
to
a8effa2
Compare
Are we done with this one? Shall we merge it? |
@cigaly? Status? |
Yes, you can merge that. |
Sorry, @cigaly I now notice there are conflicts, can you resolve them please and then I will merge? |
OK |
…irectory structure
a8effa2
to
e575c8f
Compare
@gavinking I've resolved conflict and pushed commit. |
Excellent, thanks @cigaly! |
See Jira issue HHH-18106
When named query in entity method annotated with @CheckHQL contains valid Java constant, processor should not report error