Override an existing precondition in Liquibase - java

I'm currently in the process of creating an extension for Liquibase to support Cassandra. It's working pretty well but I want to add some nice-to-have functionality.
When a changeset has a precondition, I want to throw something like a NotSuppportedException() or whatever. Problem is that currently, the underlying JDBC wrapper returns a closed ResultSet which results in an Exception being thrown upon access to said ResultSet.
For Statements, I implemented my own Generators. Is there a similar thing for preconditions? Or a way to override the existing ForeignKeyExistsPrecondition implementation? Extending from the class and overriding the check method doesn't work (even if placed in the package liquibase.precondition.ext).
Thanks!

The only way this seems to work (thanks to #dag) is using the exact same FQDN as the Precondition I want to override.

Related

Custom Validator for Static Use of Reflection vs. Custom Rule in SonarQube (Java, Eclipse)

There may be some related questions, but I think my situation is peculiar enough to justify a question on its own.
I'm working on a historically grown huge Java project (far over one million LOC, due to other reasons we're still bound to Java 6 at the moment), where reflection is used to display data in tables - reflection is not used for dynamically changing the displayed data, but just for using some kind of short cuts in the code. A simplified part of the code looks like this.
TableColumns taco = new TableColumns(Bean.class);
taco.add(new TableColumn("myFirstMember"));
taco.add(new TableColumn("mySecondMember"));
...
List<Bean> dataList = getDataFromDB(myFilterSettings);
taco.displayTable(dataList);
So the values of the table cells of each row are stored in an instance of Bean. The values for the first cell comes from calling itemOfDataList.getMyFirstMember() (so here comes the reflection part of the code). The rendering of the table cells is done depending on the return type of the itemOfDataList.getMyFirstMember().
This way, it's easy to add new columns to the table, getting them rendered in a standard way without caring about any details.
Problem of this approach: when the getter name changes, the compiler doesn't notice and there will be an exception at runtime in case Bean.getMyFirstMember() was renamed to Bean.getMyFirstMemberChanged().
While reflection is used to determine which getter is called, the needed info is in fact available at compile time, there are no variables used for the column info.
My goal: having a validator that will check at compile time whether the needed getter methods in the Bean class do exist.
Possible solultions:
modifying the code (using more specific infos, writing an adapter, using annotations or whatever that can be checked at compile time by the compiler), I explicitely don't want a solution of this kind, due to the huge code basis. I just need to guarantee that the reflection won't fail at runtime.
writing a custom validator: I guess this shouldn't be too complex, but I have no real idea how to start, we use eclipse as ide, so it should be possible to write such a custom validator - any hints for a good starting point?
The validator should show a warning in eclipse if the parameter in the TableColumn(parameter) isn't final (should be a literal or constant). The validator should show an error in eclipse if the TableColumn is added to TableColumns and the corresponding Bean.getParameter() doesn't exist.
as we use SonarQube for quality checking, we could also implement a custom rule checking if the methods do exist - not completely sure if such a custom rule is possible (probably yes)
maybe other solutions that will give a fast feedback within eclipse that some tables won't render correctly after some getter methods were renamed
What I'm asking for:
what will be easier in this situation: writing a custom validator for eclipse or writing a custom rule for SonarQube?
hints where to start either approach
hints for other solultions
Thanks for your help.
Some alternatives:
You could migrate to more modern Java for this pattern, it is a prime candidate for method references. Then, your IDE of choice can automatically take care of the problem when you refactor/rename. This can be done bit-by-bit as the opportunity/necessity arises.
You could write your own custom annotations:
Which you can probably get SonarQube to scan for
Which could allow you to take advantage of javax.validation.* goodies, so your code may look/feel more like 'standard' Java EE code.
Annotations can be covered by a processor during the build step, various build tools have ways to hook this up -- and the processor can do more advanced/costly introspection so you can push the validation to compile-time as opposed to run-time.

Hibernate 5.2.5.Final createSQLQuery() method deprecated

I'm using the createSQL() method in Hibernate to make an insert operation in my database.
What I want to do is declraing a custom SQL statement so that I can apply a MD5() function to a field on a table. That's why I can't just simply use the save(Object) method.
I got a warning from Eclipse IDE that says:
The method createSQLQuery(String) from the type QueryProducer is deprecated.
Despite of this the insert operation is performing as expected.
The current version of Hibernate I'm using on my project is 5.2.5.Final.
So, the question would be: is there another way to achieve the same in this version of Hibernate in order to get rid of that annoying warning?
I also know adding #SuppressWarnings("deprecation") annotation will solve the issue, but I'm not pretty sure whether it will cause any problems in the future.
It's worth mentioning that I'm a begginer using this framework.
The javadoc of the deprecated QueryProducer.createSQL(String) describes what to use instead:
Deprecated. (since 5.2) use createNativeQuery(String) instead
Create a NativeQuery instance for the given SQL query string.
Just adding #SuppressWarnings("deprecation") is usually no good idea,
because you may get problems in the future; i.e. when you move to a newer Hibernate version where the now deprecated method then will have been removed.

Make and load copy of SWI-Prolog Instance with JPL

What I am trying to do is create a copy of a Prolog instance and load that copy with JPL (the Java-Prolog Interface). I can think of several possible ways to do this, but none of them are completely worked out, and that is why I have come here.
First, I know I could save a copy of the state using qsave_program/2. This creates an exe file which I can run. However, I need to query this saved instance from Java using JPL. I've tried looking for documentation for this, but I couldn't find any (probably not a common issue). Is there any way I can run an instance saved using qsave_program/2 and query it from JPL?
The second idea would be to query the original instance for all dynamically asserted clauses. However, I cannot know what was asserted, so I cannot ask for those things directly, but rather I must collect these clauses based on the fact that they are dynamic. Then I could simply start another instance from JPL and assert these facts to create a copy. Is this possible? And would this effectively create a copy of the state?
Alright, here is the solution I've decided on. I can find all the predicates I will need to reassert with the following query:
predicate_property(X,dynamic),\+predicate_property(X,built_in),\+predicate_property(X,number_of_clauses(0)).
Here's why I think this will work for me.
predicate_property(X,dynamic) will give me all the dynamic predicates. The reason I don't stop here is because there are a lot of predicates that are dynamic whose clauses I don't need to explicitly assert in my new instance of prolog. Predicates that have the property built_in can be ignored, because those will be automatically defined when I create the new instance of my prolog query. Even if they are explicitly defined by the user, that definition will be reinstantiated because I am consulting the same file. I can also ignore those predicates that have no clauses (number_of_clauses(0)), because the predicates are not affecting the state if they have no clauses.
So, once I have all the dynamic predicates I want, I can find all solutions to those predicates, make a list of the Terms returned in Java through JPL, open a new consultation of the file, and reassert those Terms.

overwrite a method in a jdbc third party jar

I want to access my database through ebean. My database is a Gupta SQLBase 11.5 (don't wonder if you don't know it). The problem is that the guys at gupta are very lazy. So their implementation of java.sql.DatabaseMetaData.getDatabaseMajorVersion throws an SqlException: unsupported method. Is it possible to overwrite that method in my application so that it just returns 11? I already tried to implement my own jdbc.gupta.sqlbase.SqlbaseDatabaseMetaData class with this method which indeed works but I'm not able to implement all methods the interface needs. That is why all selects I do through ebean returns null. So I only need to overwrite the getDatabaseMajorVersion method. IMHO there is no opinion to implement a subclass which just extends the gupta class cause my class would never be taken.
thanks for every advise you can give.
best regards, Marco
You can write a wrapper, either by using the delegate pattern, or by Proxy (reflection). You will need to intercept any invocation of the "overriden" methods, and delegate the others to the underlying object.
For convenience, you could also write a wrapper for Connection, and override Connection.getMetaData(), which should return an instance of your wrapper.
If you want to go fancy, you may also register an implementation of Driver that rewrites the connection URL and returns an instance of your Connection.

Help writing JUnit for JDBC

I created one class,in which i am inserting values into SQL as follows:
public class ABC{
some code here..........
...............
public void insertUsers(String firstName,String lastName,String location){
pre.setString(1,firstName);
I created test class for this class.
I want to write test case for this method insertUsers(),using assert statement.
how to write assert statement for above method.
When doing unit testing one should avoid accessing external resources such as databases, filesystems, network etc. This is to keep the tests in memory (fast), but also isolated from external failures. You only want to test a specific part of some functionality in e.g. a class, nothing else.
What this means for you is that the conn variable (I assume is the db connection) needs to be mocked out. You can do this easily with something like dependency injection, which means you pass in things into your class when constructing it. In this case you would pass in an interface which has the necessary functions conn uses.
Then in production you pass in the real db connection object while in test you pass in a mock which you control. Hence, you can then check that ABC calls and does what you expect it to do with conn. The same goes for pre you're using.
You can see it like this: I would like to test class ABC, and in order to do that I need to see how it uses pre and conn, so I replace those with my own test implementations I can check after doing something with ABC.
In order to specifically help you with what you're doing you need to show what pre is and tell us what you intend to test.
Well if you really want to test updating your database you can do that. Usually people follow one of the below two approaches -
Use Spring AbstractTransactionalDataSourceSpringContextTests This allows you to add any values to the database and then spring will take care and revert the values that you have inserted.
Use a seperate database Just for your JUnit tests. You really dont need anything heavy. You can use something like the HSQLDB which is really a lightweight java database. This will allow you to have separate test data from your production/QA database.
After the above is done(and you have run the insert statement) simply run select statement from your JUnit to get the data and then compare the previous data with the actual data.
A couple of remarks.
I'd use the standard assert during development only. It will check a condition and throw a runtime exception, if the condition evaluates to false.
If you expect illegal arguments, than it's much better to add some "normal" code to the method to handle those values or throw an IllegalArgumenException and write log entry.
Do not close the connection in this method! Do it only when you open/create the connection in the very same method. In larger applications you won't be able find out who closed the connection after a while. If the caller of insertUsers opened the connection, the caller should close it itself!
(more help possible if you tell us what exactly you want to test - the method parameters or if the insert was a success)
I wouldnt test the insertion of the data to the database, actually its not performant to access database during unittesting, this can be covered threw automated functional GUI testing tools of your application.
what you may want to test is the generation of the expected queries, this can realised if you seperate the geenration and the execution of the statements, you will be able to compare generated statements with expected ones without having to access you database from the unitest.

Categories

Resources