We're happy to announce VisionX 5.11.615
The new version is fully backwards compatible and contains many improvements. It also fixes some reported problems and brings new features. This version is the last version of series 5 and we didn't change bigger blocks. The 5.11.615 should be a great final version of VisionX 5. We already started development of VisionX 6 and it will bring some bigger changes because we'll update to Java 21. We also will update our embedded postgresql database. We'll update to our latest react based UI and also to latest mobile app. We have some great features in the pipeline for all of you.
... back to VisionX 5.11.615
What's new?
- NEW calculated field
Calculated field
Use this field for sum, average, min, max calculation or simple record counts. The calculated value can be changed after calculation or you can define custom formulas. It's on you. It's super easy to use and you can access the calculated fields in any action.
- Actions and Functions
Our new actions are:
- Perform search
If you have a "manual" Search button in your screen, automatic search is disable automatically. With this action it's possible to force search)
- Download URL
Save data from an URL.
- Contains (value, search, case_sensitive)
Checks if a search value is part of a specific value. case_sensitive means (B is not the same as b; but case insensitive means B is the same as b)
- Starts with (value, search, case_sensitive)
Checks if a value starts with a specific search value
- Ends with (value, search, case_sensitive)
- for loop with fixed number of iterations
Checks if a value ends with a specific search value
Changed actions:
- E-Mail
It's now possible to set dynamic text as subject instead of fixed text.
We have some totally useful new functions for you:
- length (text)
Counts the number of characters
- substring (text, start)
Creates a sub string from start to the end
- substring (text, start, count)
Creates a sub string from start and maximum count characters
- countAll (column)
Counts all records. Compared to count(column) which counts all records where the value is not empty.
The description of an action shows possible functions as well:
Detailed description
Improved field selection
Choose field
Messages now support feedback input
Feedback input
Changing license is now possible without "invalid license" warning
Changed some icons in elements area of visual designer
Creation of XML reports fixed
Starting with VisionX 5.11.615 it will be possible to use updates of following AddOns:
- Embedding 1.8-4
- Audit Log 1.2-11
- REST 1.14-ea10
- Query Editor 1.4.6
As usual, VisionX 5.11.615 is available in the download area for our customers or as trial.
Have fun!
Part 1 of this article is available here.
Since Java 14, ClassLoader was changed a little bit and usr_paths it not available as field anymore. It's still possible to change the java.library.path at runtime, but it's still tricky and dirty:
Method getDeclaredFields0
=
Class.
class.
getDeclaredMethod("getDeclaredFields0",
boolean.
class);
getDeclaredFields0.
setAccessible(true);
Field[] fieldsClassLoader =
(Field[])getDeclaredFields0.invoke(ClassLoader.class, Boolean.FALSE);
for (Field fldClassLoader : fieldsClassLoader) {
if ("libraries".equals(fldClassLoader.getName())) {
fldClassLoader.setAccessible(true);
Class<?>[] classesClassLoader =
fldClassLoader.getType().getDeclaredClasses();
for (Class<?> clLibraryPaths : classesClassLoader) {
if ("jdk.internal.loader.NativeLibraries$LibraryPaths".equals(
clLibraryPaths.getName())) {
Field[] fieldsLibraryPaths =
(Field[])getDeclaredFields0.invoke(clLibraryPaths, Boolean.FALSE);
for (Field fldLibPath : fieldsLibraryPaths) {
if ("USER_PATHS".equals(fldLibPath.getName())) {
final Field fldUsrPaths = fldLibPath;
fldUsrPaths.setAccessible(true);
// get array of paths
final String[] saPath = (String[])fldUsrPaths.get(null);
// check if the path to add is already present
for (String path : saPath) {
if (path.equals(pPath)) {
return;
}
}
// add the new path
String[] saNewPaths = Arrays.copyOf(saPath, saPath.length + 1);
saNewPaths[saNewPaths.length - 1] = pPath;
Object unsafe;
// Unsafe is a hack
Class<?> clsUnsafe = Class.forName("sun.misc.Unsafe");
final Field unsafeField = clsUnsafe.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
unsafe = unsafeField.get(null);
Method m1 = clsUnsafe.getMethod("staticFieldBase", Field.class);
Method m2 = clsUnsafe.getMethod("staticFieldOffset", Field.class);
Object fieldBase = m1.invoke(unsafe, fldUsrPaths);
Long fieldOffset = (Long)m2.invoke(unsafe, fldUsrPaths);
Method m3 = clsUnsafe.getMethod("putObject", Object.class,
long.class, Object.class);
m3.invoke(unsafe, fieldBase, fieldOffset, saNewPaths);
}
}
}
}
return;
}
}
Here's the complete solution: toPDF project (search for addLibraryPath(String pPath))
Above code requires:
--add-opens java.base/java.lang=ALL-UNNAMED
--add-opens java.base/jdk.internal.loader=ALL-UNNAMED
for JDK > 14.