Java Date/time class supported in new workbench Test Scenario? - drools

Is there a date/time type supported by the new business central workbench test scenarios? java.time.LocalDateTime does not appear to work although for dates java.time.LocalDate does work

There is no embedded support for java.time.LocalDateTime but starting from version 7.30 we support MVEL expressions in RULE based test scenarios: it is enough to add # as prefix to the value and then you can invoke the Java method that you prefer.
In EXPECT section you can use an implicit variable named actualValue to have access to the value of that column

Support to LocalDateTime and LocalTime was added since version 7.47.0.

Related

Converting a integer to date

I am having an issue with converting an integer date (20180525) to a date in the format of YYYY-MM-DD. Is there a way to do this or should I just convert it in code (Java in this case)? Any help with this would be most appreciated. Thank you!
if your dates are stored as integers with YYYYMMDD, you can pass it to the date function by first casting to TEXT.
SELECT date(20180525::TEXT)
otherwise, use the function to_date with a date formatter:
SELECT to_date(20180525::text, 'YYYYMMDD')
tl;dr
Either SQL or Java works well. For SQL, see the correct Answer by Ali.
For Java, pass a LocalDate to a PreparedStatement query.
LocalDate.parse( // `LocalDate` represents a date-only value without time-of-day and without time zone. Works with SQL-standard `DATE` type.
Integer.toString( 20180525 ) , // Convert integer to text, for a `String` object as input.
DateTimeFormatter.BASIC_ISO_DATE // Specify a formatting pattern to match our input string.
) // Returns a `LocalDate` object.
2018-05-25
java.time
Regarding Java mentioned in the Question, here is code using the modern java.time classes. Whether you should use SQL or Java to parse you string depends on your situation and your tastes, as either route works.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone.
You need to specify a formatting pattern to match your input. In this particular case, your input string is in standard ISO 8601 format. Specifically, the “basic” variant of ISO 8601 formats that minimize the use of delimiters. In java.time, you will find this particular formatting pattern is conveniently predefined for you.
String input = Integer.toString( 20180525 ) ; // Convert integer to text for input as `String`.
DateTimeFormatter f = DateTimeFormatter.BASIC_ISO_DATE ;
LocalDate ld = LocalDate.parse( input , f ) ;
ld.toString(): 2018-05-25
JDBC
As of JDBC 4.2 and later, you can directly exchange java.time objects with your database. Always better to use smart objects rather than dumb strings.
String sql = "SELECT event_date FROM tbl WHERE event_date = ? ; " ;
…
myPreparedStatement.setObject( 1 , ld ) ;
And retrieval.
LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
select ((field_int)::text)::date as field_date from your_table;

Using the java.time API in scala

I'm trying out Java 8 Date Time Api java.time using Scala REPL. Just encountered the problem below:
I do understand that the keyword with is reserved in scala, but also it is used in the API. Any idea on how to mitigate the limits?
Try wrapping the with with tick marks as follows:
val nextWed = today.`with`(java.time.temporal.TemporalAdjusters.next(DayOfWeek.WEDNESDAY))
Adding the ticks designates it a literal identifier.

Scala conversion long to datetime

I am using nscala-time (wrapper for Joda Time) and slick for a project. I'm trying to use this clause to write a line to the database:
Article.insert(0,"title1", "hellothere", DateTime.now.getMillis.asInstanceOf[Timestamp])
Apparently Slick does not support "dateTime" type defined in Joda Time, and I have to use java.sql.Timestamp instead. So I decide to do a little conversion inside the insert method, using "asInstanceOf". Unfortunately, Scala quickly tells me that Java.Long cannot be converted to Java.sql.Timestamp. Then I used this:
val dateTime = new DateTime();
val timeStamp = new Timestamp(dateTime.getMillis());
Article.insert(0,"title1", "hellothere", timeStamp)
This magically works, and all I'm left with is confusion.
How can I convert it one way but not the other? Should I use a different conversion than asInstanceOf?
You misunderstand what asInstanceOf does: asInstanceOf doesn't convert anything. What it does is lie to the compiler, telling it to believe something instead of going with the knowledge it has.
So, you had a Long, and then you got a Long, but pretended it was a Timestamp, which obviously doesn't work.
I have a simple recommendation regarding asInstanceOf: never use it.
There's no magic about it. Your first statement:
DateTime.now.getMillis
is a Long. A Long is not a Timestamp, so it makes sense that you can't convert it to one by using asInstanceOf.
The second statement:
new Timestamp(dateTime.getMillis())
is using the Timestamp constructor to create a new Timestamp instance based on the dateTime.getMillis.

Calling Scala from Groovy: How to handle different collection types?

I'm using Groovy for testing and Scala for actual code. Obviously I often use Scala's collection types - but when I generate test data in Groovy I often use the java.util.*-types.
I started writing static conversion methods based on the scalaj-collection library. But that's just not 'groovy'.
What's the best approach to convert one to the other?
Might implicit conversions work somehow?
UPDATE:
For example if I wouldn't manually convert the types I of course get:
groovy.lang.MissingMethodException:
No signature of method: static setup is applicable for argument types: (java.util.ArrayList)
Possible solutions: setup(scala.collection.immutable.List)
Did you try the "built-in" implicit conversions?
import scala.collection.JavaConversions._
Another approach is to change your Scala code to use Java collection types when declaring parameters and rely on implicit conversions in the method body to get the benefit of Scala collections operations.

Does Scala have introspection capable of something similar to Python's dir()?

Yes, I know it's considered lazy by the non-Pythonistas. The reason I ask is that documentation is still woefully lacking in many Scala libraries (e.g. Scala-dbc, but that's not all I'm looking at), and if I could see the attributes of an object/class at runtime, I could at least figure out what's available. Thanks.
Scala does not have a reflection API. The only way to access this information is to use the Java reflection API. This has the disadvantage that the structure may change as the way Scala is represented in Java classes and interfaces may change in the future.
scala> classOf[AnyRef].getMethods
res0: Array[java.lang.reflect.Method] = Array(public final void ...
Some specific type information that is present in the byte code can be accessed with the ScalaSigParser.
import tools.scalap.scalax.rules.scalasig._
import scala.runtime._
val scalaSig = ScalaSigParser.parse(classOf[RichDouble])
That's one of my main uses for REPL. Type the object's name, dot, and then TAB and it will show all available methods.
It isn't perfect. For one thing, it shows protected methods, which won't be available unless you are extending the class. For another thing, it doesn't show methods available through implicit conversion.
And, of course, the IDEs are all capable of doing that.
You might want something like the following which would give you what you need. In this case, it operates on a String, obviously.
val testStr = "Panda"
testStr.getClass.getMethods.foreach(println)
Does that work?
You may want to use this little helper to beef up the REPL