Over the next several releases, Veeva is upgrading the Vault Java SDK compilation from Java 8 to Java 17. Java 17 includes optimizations that can improve performance and efficiency compared to Java 8, allowing for reduced resource usage.
Existing integrations are not affected as long as developers do not update or modify existing integration code. When Java 17 is enabled, Vault compiles code deployments with Java 17 instead of Java 8. If no code is deployed, there is no behavior change. Updating or modifying an existing integration requires deployment, which means that updating an existing integration compiled with Java 8 will cause the integration to recompile with Java 17.
Until 25R2, Admins can disable Java 17 to allow developers to modify existing integrations and deploy with Java 8 compilation. After 25R2, Admins can no longer disable Java 17 compilation.
We recommend developers test their code using Java 17 as soon as possible, which will allow developers to modify existing integrations if needed after 25R2. After 25R2, all code will compile with Java 17. At this time, existing integrations compiled with Java 8 cannot be modified without changing compilation from Java 8 to Java 17.
The upgrade to Java 17 may require code changes to keep custom integrations working with Java 17 compilation. To help with this migration, we’ve created a list of solutions to common Java 17 compilation errors.
The upgrade to Java 17 may require code changes. We recommend developers enable Java 17 and test their code as soon as possible.
When enabled, the Use Java 17 Compilation and Runtime setting causes Vault code deployments to compile with Java 17. Enabling Java 17 compilation in your Vault does not automatically test your code for compatibility, as existing code is not recompiled. To test your code for compatibility with Java 17, you must enable Java 17 in your Vault and then redeploy any existing custom code to recompile with Java 17.
To enable Java 17:
When Java 17 is enabled:
The upgrade to Java 17 may require code changes. If your organization needs more time to make these changes, you can temporarily disable Java 17. Disabling Java 17 allows your developers to modify your existing integrations without upgrading to Java 17 yet. Organizations must upgrade by 25R2 (25R1.2), at which time the option to disable Java 17 will no longer be available.
To disable Java 17:
When Java 17 is disabled:
When evaluating custom code for compatibility with Java 17, developers may want to start by making no changes and redeploying existing code as-is in a sandbox Vault. This will evaluate if code changes are needed for the upgrade to Java 17 compilation.
To redeploy existing code without making changes:
replace_all
deployment option.If code incompatibilities are found, developers should deploy code changes with the Maven Plugin. For example, developers may need to deploy changes for common Java 17 compilation errors.
To test your code with Java 17 locally, you must make the following change to your POM file:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<!-- Source will still be Java 8 -->
<source>1.8</source>
<!-- compile using Java 17 -->
<target>17</target>
</configuration>
</plugin>
The following solutions can help you fix common issues you may encounter when upgrading to Java 17.
Can’t find your issue? Let us know in the Vault for Developers community on Veeva Connect.
Summary of Issue:
import com.veeva.vault.sdk.api.data.*
), the Java 17 compiler cannot determine which Record
class is being referencedThe following example code demonstrates the Java Record Class error:
package com.veeva.vault.custom.triggers;
import com.veeva.vault.sdk.api.data.*;
@RecordTriggerInfo(object = "vsdk_hello_world__c", name="vsdk_hello_world__c", events = {RecordEvent.BEFORE_INSERT})
public class HelloWorld implements RecordTrigger {
public void execute(RecordTriggerContext recordTriggerContext) {
LogService logService = ServiceLocator.locate(LogService.class);
// is this java.lang.Record, or com.veeva.vault.sdk.api.data.Record?
Record record = recordTriggerContext.getRecordChanges().get(0).getNew();
}
}
Compiling the affected code example produces the following error:
MESSAGE "[type=INVALID_DATA,message=javasdk/src/main/java/com/veeva/vault/custom/triggers/HelloWorld.java:51: error: reference to Record is ambiguous
Record record = recordTriggerContext.getRecordChanges().get(0).getNew();
^
both interface com.veeva.vault.sdk.api.data.Record in com.veeva.vault.sdk.api.data and class java.lang.Record in java.lang match
Provide a specific import statement for the Record
class.
package com.veeva.vault.custom.triggers;
import com.veeva.vault.sdk.api.data.Record;
import com.veeva.vault.sdk.api.data.RecordChange;
import com.veeva.vault.sdk.api.data.RecordEvent;
import com.veeva.vault.sdk.api.data.RecordTrigger;
import com.veeva.vault.sdk.api.data.RecordTriggerContext;
import com.veeva.vault.sdk.api.data.RecordTriggerInfo;
@RecordTriggerInfo(object = "vsdk_hello_world__c", name="vsdk_hello_world__c", events = {RecordEvent.BEFORE_INSERT})
public class HelloWorld implements RecordTrigger {
public void execute(RecordTriggerContext recordTriggerContext) {
LogService logService = ServiceLocator.locate(LogService.class);
// Now it is clear this is com.veeva.vault.sdk.api.data.Record
Record record = recordTriggerContext.getRecordChanges().get(0).getNew();
}
}
Summary of Issue:
_
) is a keyword in Java 17The following example code demonstrates the Underscore Keyword error:
package com.veeva.vault.custom.triggers;
import com.veeva.vault.sdk.api.data.Record;
import com.veeva.vault.sdk.api.data.RecordChange;
import com.veeva.vault.sdk.api.data.RecordEvent;
import com.veeva.vault.sdk.api.data.RecordTrigger;
import com.veeva.vault.sdk.api.data.RecordTriggerContext;
import com.veeva.vault.sdk.api.data.RecordTriggerInfo;
@RecordTriggerInfo(object = "vsdk_hello_world__c", name="vsdk_hello_world__c", events = {RecordEvent.BEFORE_INSERT})
public class HelloWorld implements RecordTrigger {
public void execute(RecordTriggerContext recordTriggerContext) {
LogService logService = ServiceLocator.locate(LogService.class);
// Cannot use underscore (_) as identifier
Record _ = recordTriggerContext.getRecordChanges().get(0).getNew();
// Cannot use underscore (_) as identifier
List<BigDecimal> bgdList = VaultCollections.newList();
bgdList.stream().forEach(_ -> _.add(new BigDecimal(14)));
}
}
Compiling the affected code example produces the following error:
java: as of release 9, '_' is a keyword, and may not be used as an identifier
java: '_' used as an identifier
(use of '_' as an identifier is forbidden for lambda parameters)
Replace all identifiers using an underscore (_
) with a different, non-keyword String.
package com.veeva.vault.custom.triggers;
import com.veeva.vault.sdk.api.data.Record;
import com.veeva.vault.sdk.api.data.RecordChange;
import com.veeva.vault.sdk.api.data.RecordEvent;
import com.veeva.vault.sdk.api.data.RecordTrigger;
import com.veeva.vault.sdk.api.data.RecordTriggerContext;
import com.veeva.vault.sdk.api.data.RecordTriggerInfo;
@RecordTriggerInfo(object = "vsdk_hello_world__c", name="vsdk_hello_world__c", events = {RecordEvent.BEFORE_INSERT})
public class HelloWorld implements RecordTrigger {
public void execute(RecordTriggerContext recordTriggerContext) {
LogService logService = ServiceLocator.locate(LogService.class);
// Replaced underscore (_) identifier with non-keyword String
Record record = recordTriggerContext.getRecordChanges().get(0).getNew();
// Replaced underscore (_) identifier with non-keyword String
List<BigDecimal> bgdList = VaultCollections.newList();
bgdList.stream().forEach(bd -> bd.add(new BigDecimal(14)));
}
}