Javascript Remoting Update causing INVALID_TYPE_ON_FIELD_IN_RECORD for Integers

After quite a bit of testing, this does seem like a bug to me. I wasn't able to make this work, and did quite a bit of fiddling with data types, setting input type on the input tag to number, etc.

I found a workaround, using a wrapper class to accept the payload for the remote action call, then copying that into an account object in the Apex code. This requires a bit more effort and code, but it seems to work.

My example is also making use of a second field AnnualRevenue which I was using in comparison to NumberOfEmployees just for testing purposes.

Visualforce Page

<script>
function putAccountWithWrapper(){

    var acct = {};
    acct.RecId = document.getElementById("accountPutId").value;
    acct.Employees = document.getElementById("accountPutNumEmp").value ? document.getElementById("accountPutNumEmp").value : null;
    acct.AnnualRev = document.getElementById("annRev").value ? document.getElementById("annRev").value : null;

    console.log(acct);
    RemoteApexTestNumOfEmployees.putAccountWithWrapper(acct, function(result, event){
        console.log(event);
    });
}
</script>
<div>
    <input id="accountPutId" type="text" placeholder="Id"/>
    <input id="accountPutNumEmp" type="number" placeholder="Num Of Employees"/>
    <input id="annRev" type="number" placeholder="Revenue"/>
    <button onClick="putAccountWithWrapper()">
        Go Using Wrapper
    </button>
</div>

In this one, I copy Id, but the other two fields, I am explicity setting fields to null when no value is present. There are other ways to do this, perhaps, but I'll use this in the controller to make certain I'm not accidentally nulling out values that already exist.

Apex Class

public class RemoteApexTestNumOfEmployees {

    @RemoteAction
    public static void putAccountWithWrapper(Wrapper w){

        Account a = new Account();

        a.Id = w.RecId;
        if (w.Employees != null) a.NumberOfEmployees = w.Employees ;
        if (w.AnnualRev != null)a.AnnualRevenue = w.AnnualRev ;

        update a;

        System.debug('nothing');
    }

    public class Wrapper {
        public Id RecId;
        public Integer Employees; 
        public String Name;
        public Decimal AnnualRev;
    }
}

Here again, I'm looking for nulls and not initializing the fields in the sObject when nulls are passed in so I'm not overwriting existing data.

Using the wrapper, I was finally able to get NumberOfEmployees to save.