function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Mike LeachMike Leach 

JavaScript Remoting calls not working from managed package

JS Remoting works fine in a managed package within Visualforce pages.

 

However, when moving the @RemoteAction to an extension for an inline VF page, it stops working. Example code taken directly from this HOWTO article.

 

The remoting action silently fails to console log with the following error messages:

Controller not found for 'IO.LineItemRemotingExtension' VFRemote.js:114
Unable to invoke action 'IO.LineItemRemotingExtension.getAccountRemote': no controller and/or function found VFRemote.js:114
$VFRM.Util.error VFRemote.js:114
$VFRM.ProviderManager.VFExt3.extend.invokeAction VFRemote.js:134
getRemoteAccount servlet.Integration:19
onclick

 

Visualforce Page (inline)

<apex:page showHeader="false" sidebar="false" standardController="Order__c" extensions="LineItemRemotingExtension" standardstylesheets="true">

<head>  
	<script type="text/javascript">
	function getRemoteAccount() {
		var accountName = document.getElementById('acctSearch').value;
		
		Visualforce.remoting.Manager.invokeAction(
			'{!$RemoteAction.LineItemRemotingExtension.getAccountRemote}',
			accountName, 
			function(result, event){
				if (event.status) {
					// Get DOM IDs for HTML and Visualforce elements like this
					document.getElementById('remoteAcctId').innerHTML = result.Id
					document.getElementById(
						"{!$Component.block.blockSection.secondItem.acctType}"
					).innerHTML = result.Type;
				} else if (event.type === 'exception') {
					document.getElementById("responseErrors").innerHTML = 
						event.message + "<br/>\n<pre>" + event.where + "</pre>";
				} else {
					document.getElementById("responseErrors").innerHTML = event.message;
				}
			}, 
			{escape: true}
		);
	}
	</script>
</head>

<input id="acctSearch" type="text"/>
<button onclick="getRemoteAccount()">Get Account</button>
<div id="responseErrors"></div>

<apex:pageBlock id="block">
	<apex:pageBlockSection id="blockSection" columns="2">
		<apex:pageBlockSectionItem id="firstItem">
			<span id="remoteAcctId"/>
		</apex:pageBlockSectionItem>
		<apex:pageBlockSectionItem id="secondItem">
			<apex:outputText id="acctType"/>
		</apex:pageBlockSectionItem>
	</apex:pageBlockSection>
</apex:pageBlock>

 

Apex Controller Extension

global with sharing class LineItemRemotingExtension {	
	private final Order__c m_order;
	
	public LineItemRemotingExtension(ApexPages.StandardController stdController) {
		String oid = stdController.getRecord().Id;
		this.m_order = Database.query('SELECT ' + Order.SFIELDS + ' FROM Order__c WHERE Id=:oid LIMIT 1');
	}
	
	@RemoteAction
	global static Account getAccountRemote(String accountName) {
		return [SELECT Id, Name, Phone, Type, NumberOfEmployees 
			FROM Account WHERE Name = :accountName];
	}
}

 

Tried replacing the call to {!$RemoteAction.LineItemRemotingExtension.getAccountRemote} with just plain 
RemoteAction.LineItemRemotingExtension.getAccountRemote

-and-
IO.RemoteAction.LineItemRemotingExtension.getAccountRemote

 

But neither option works. It doesn't appear to be a managed package namespace issue, but more like a controller extension related anomoly. 

 

Any one else encountered this, or have thoughts/suggestions?

 

Thanks!

 

-Mike

 

Edit: Per Josh's suggestion, I've tried binding directly to the controller extension name/method, bypassing invokeMethod. This this also does not work, throwing different exceptions with and without namespace prefix. Examples below:

 

<script type="text/javascript">
	function getRemoteAccount() {
		var accountName = document.getElementById('acctSearch').value;
		
		LineItemRemotingExtension.getAccountRemote(accountName, 
			function(result, event){
				if (event.status) {
					alert("success");
				} else if (event.type === 'exception') {
					alert(event.message);
				} else {
					alert(event.message);
				}
			}, 
			{escape: true}
		);
	}
</script>

 

 Exception: Uncaught ReferenceError: LineItemRemotingExtension is not defined servlet.Integration:19

    1. getRemoteAccountservlet.Integration:19
    2. onclick

 

With namespace prefix:

 

IO.LineItemRemotingExtension.getAccountRemote

Exception: Uncaught TypeError: Cannot call method 'getAccountRemote' of undefined servlet.Integration:19

    1. getRemoteAccount servlet.Integration:19
    2. onclick



Best Answer chosen by Admin (Salesforce Developers) 
Mike LeachMike Leach

FIXED / RESOLVED

 

TL;DR: This was discovered to be a javascript namespace conflict bug. Not related to the Salesforce remoting manager.

 

Details:

The Remoting manager generated a javascript namespace from the managed package prefix; in this case "IO". The controller methods are then available with the syntax namespace.controller.method.

 

The conflict occured when an imported static resource JS library contained the same namespace prefix.

 

Resolution:

Update the JS static resource with a non conflicting namespace.

All Answers

joshbirkjoshbirk

Definitely avoid talking to the remote manager directly, even if it works now it's possible it will fail in the future if the manager implementation changes.

 

When I pull just a simple controller and the remote logic into a DE org with no managed package, it works as expected.  As a guess, did you try:

 

IO_LineItemRemotingExtension.getAccountRemote

 


I haven't used Remoting in many managed packages, but that might fit the namespace requirement.  The abstracted JavaScript object for the extension remote should be visible within the console, so a quick way to see the function is available is to simply log it.  For instance, in an unmanaged package:

 

console.log(LineItemRemotingExtension);

 



Displays the expected function.

Mike LeachMike Leach

FIXED / RESOLVED

 

TL;DR: This was discovered to be a javascript namespace conflict bug. Not related to the Salesforce remoting manager.

 

Details:

The Remoting manager generated a javascript namespace from the managed package prefix; in this case "IO". The controller methods are then available with the syntax namespace.controller.method.

 

The conflict occured when an imported static resource JS library contained the same namespace prefix.

 

Resolution:

Update the JS static resource with a non conflicting namespace.

This was selected as the best answer