forcedotcom / wsc

Other
271 stars 222 forks source link

Error when compiling Tooling API Java Bindings (enum constant value starting with the number) #334

Open bereg2k opened 2 months ago

bereg2k commented 2 months ago

Tooling API WSDL generates the XML file with the following element inside of it:

<xsd:simpleType name="CalculatedInsightPublishScheduleInterval">
<xsd:restriction base="xsd:string">
 <xsd:enumeration value="0"/>
 <xsd:enumeration value="1"/>
 <xsd:enumeration value="6"/>
 <xsd:enumeration value="12"/>
 <xsd:enumeration value="24"/>
</xsd:restriction>
</xsd:simpleType>

However, when compiling Java Bindings for the SOAP API for it, the execution fails:

Logs:

[WSC][ForkJoinWorkerThread.run:165]Generating Java files from schema ...
[WSC][ForkJoinWorkerThread.run:165]Generated 2474 java files.
Error at Line: 18, enum constant expected here in /var/folders/xj/19zsgqxd3_s66jm1st8xqvxm0000gn/T/wsc-scratch2673595683628563348tmp/com/sforce/soap/tooling/CalculatedInsightPublishScheduleInterval.java 
Error at Line: 61, <identifier> expected in /var/folders/xj/19zsgqxd3_s66jm1st8xqvxm0000gn/T/wsc-scratch2673595683628563348tmp/com/sforce/soap/tooling/CalculatedInsightPublishScheduleInterval.java 
Error: Failed to compile

This is the underlying Java class which the script is trying to create from the XML element:

CalculatedInsightPublishScheduleInterval.java

package com.sforce.soap.tooling;

import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;

/**
 * This is a generated class for the SObject Enterprise API.
 * Do not edit this file, as your changes will be lost.
 */
public enum CalculatedInsightPublishScheduleInterval {

        /**
         * Enumeration  : 0
         */
        0("0"),

        /**
         * Enumeration  : 1
         */
        1("1"),

        /**
         * Enumeration  : 6
         */
        6("6"),

        /**
         * Enumeration  : 12
         */
        12("12"),

        /**
         * Enumeration  : 24
         */
        24("24"),

;

        public static Map<String, String> valuesToEnums;

        static {
                valuesToEnums = new HashMap<String, String>();
                for (CalculatedInsightPublishScheduleInterval e : EnumSet.allOf(CalculatedInsightPublishScheduleInterval.class)) {
                        valuesToEnums.put(e.toString(), e.name());
                }
        }

        private String value;

        private CalculatedInsightPublishScheduleInterval(String value) {
                this.value = value;
        }

        @Override
        public String toString() {
                return value;
        }
}

Having enum values like this won't compile because it's incorrect Java syntax: 0("0"), 1("1")

Is it possible to work around this by compiling such enumerations using the _ symbol in the beginning? Like this: _0("0"), _1("1")


Library version in Maven POM:

<dependency>
    <groupId>com.force.api</groupId>
    <artifactId>force-wsc</artifactId>
    <version>62.0.0</version>
</dependency>
CloudStudioInc commented 2 months ago

@bereg2k I am also seeing this issue. It is preventing me from generating new stub files for the tooling api >60.0. This is a problem because as new api versions are released, if code is not kept up to date, it can fail when parsing org metadata.

CloudStudioInc commented 2 months ago

@bereg2k fyi, I've also reported this issue inside the partner community. I'm hoping this will get some movement. I see you mentioned a workaround, but those classes are not actually available to us, right?

bereg2k commented 2 months ago

@CloudStudioInc they are available because you can clone this repo, make adjustments as you see fit, and build a project locally :) Then use it with your WSDL. I tried this route – worked for me.

The easiest route though... make minor adjustments to the CalculatedInsightPublishScheduleInterval in the Tooling XML to make the tool build your JAR bindings (edit the enum values, remove the type... whatever works).

alcabon commented 3 weeks ago

The tooling.xml (and strong typed) has always problems for the generation of the jar with wsc.

https://mvnrepository.com/artifact/com.force.api/force-wsc : 62.0 https://mvnrepository.com/artifact/com.force.api/force-partner-api : 62.0 https://mvnrepository.com/artifact/com.force.api/force-metadata-api : 62.0 https://mvnrepository.com/artifact/com.force.api/force-apex-api : 62.0

(the jars above are always updated correctly)

and

https://mvnrepository.com/artifact/com.force.api/force-tooling-api : 32.0 (2018), for many years now, we had almost always problems for the generation of this jar. That seems deliberate given that it is a very complicated generation with maven that works fine for the other xml (mvnrepository ALWAYS updated including all the sub-versions). I don't know why because by removing the next type (degraded version) that works for tooling.xml (not sufficient for the strongly typed).

**Perplexity AI:** You're right to point out this issue. The XML you've provided for the CalculatedInsightPublishScheduleInterval type is problematic because it uses numeric values as enumeration values within a string restriction. This can lead to issues with code generation and type safety in strongly-typed languages like Java. **Here's how we can address this issue:** **Understand the Problem:** The WSDL defines a simple type with string restriction, but uses numeric values for the enumeration. This is not ideal for generating clean, type-safe code. **Potential Solutions:** **a) Ideal XML Structure:** Ideally, the XML should be structured like this: This would generate a proper integer-based enum in Java. **b) Custom Type Mapping:** If you can't change the WSDL, you might need to implement a custom type mapping in your WSC configuration or in your code. **Workaround for WSC:** Since WSC doesn't provide built-in customization for this scenario, you have a few options: **a) Manual Post-Processing:** Generate the code using WSC, then manually modify the generated Java enum to use integers instead of strings. **b) Custom Enum Wrapper:** Create a custom enum that wraps the generated string-based enum: public enum CalculatedInsightPublishScheduleIntervalWrapper { ZERO(0, "0"), ONE(1, "1"), SIX(6, "6"), TWELVE(12, "12"), TWENTY_FOUR(24, "24"); private final int value; private final String stringValue; CalculatedInsightPublishScheduleIntervalWrapper(int value, String stringValue) { this.value = value; this.stringValue = stringValue; } public int getValue() { return value; } public String getStringValue() { return stringValue; } public static CalculatedInsightPublishScheduleIntervalWrapper fromString(String stringValue) { for (CalculatedInsightPublishScheduleIntervalWrapper e : values()) { if (e.stringValue.equals(stringValue)) { return e; } } throw new IllegalArgumentException("Unknown value: " + stringValue); } } **c) Custom XmlAdapter:** If you're using JAXB, you can create a custom XmlAdapter to convert between the string representation and an integer: public class CalculatedInsightPublishScheduleIntervalAdapter extends XmlAdapter { @Override public Integer unmarshal(String v) throws Exception { return Integer.parseInt(v); } @Override public String marshal(Integer v) throws Exception { return v.toString(); } } Then use it in your generated or custom classes: @XmlJavaTypeAdapter(CalculatedInsightPublishScheduleIntervalAdapter.class) private Integer interval; **Report the Issue:** - **If this WSDL is provided by a third-party service, consider reporting this as an issue to them.** - **Using string-based enumerations for numeric values is not a best practice and can cause issues for consumers of the API.** - These workarounds should help you handle the improperly structured XML in your WSC-generated code. - Choose the approach that best fits your project's needs and constraints.
bereg2k commented 3 weeks ago

@alcabon My issue here is that CalculatedInsightPublishScheduleInterval in question is standard built-in type that's controlled by Salesforce.

alcabon commented 3 weeks ago

@bereg2k I know that CalculatedInsightPublishScheduleInterval in question is a standard built-in type that's controlled by Salesforce and none of the AI potential solutions works (purely theoretical and it is intended for the Salesforce developers, AI can help them in order to understand their error that block the generation (it is not a major errror but a critical one)).

- If this WSDL is provided by a third-party service, consider reporting this as an issue to them.

That is the only possible action. Otherwise, I removed the wrong types many times (degraded versions but still working). We cannot "correct" these errors because it is controlled by Salesforce.