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
TehNrdTehNrd 

Identifying what server the code is on (cs1, na3, eu0, etc)

I looked through the Apex documentation and I didn't see any methods that return the server the code is executing on. I figure it has to be there and I'm just missing it as this would be required for packaged apps so they scales across all servers.

What I am doing is build a string that is a hyperlink but I need the server instance (na3, cs1) so I can build out the correct link.

opp is a Opportunity object.
String link = 'https://na3.salesforce.com/'+ opp.id;

Hard coding the na3 is not a good solution. Maybe there is some other way to do this?

Perhaps:

String link = opp.getLink();

but I didn't see anything like this.

Thanks for the help.
-Jason
Best Answer chosen by Admin (Salesforce Developers) 
TehNrdTehNrd
FYI,

http://ideas.salesforce.com/article/show/10091004/Apex_method_to_identify_salesforcecom_server

All Answers

TehNrdTehNrd
Anyone?
Jon KeenerJon Keener
I had to do the same thing, and basically found out what you did, that APEX doesn't provide a way to get to this information.
 
So my workaround was the following:
 
I created a custom object called Salesforce_System_Info__c.
 
This custom object has one field in it: URL_Prefix__c.  In my case, I made it a picklist and added our sandbox and production values:
 
 
I then added one record to this table, which had the correct URL Prefix selected.
 
 
Then, I created a simple APEX Class to retrieve the correct URL:
 
Code:
public class Salesforce_System_Info_Functions {

  private static String URL_Prefix = '';

  public static String Retrieve_URL_Prefix() {
    String result = '';

    if (URL_Prefix == '')
        {URL_Prefix = [SELECT URL_Prefix__c FROM Salesforce_System_Info__c LIMIT 1].URL_Prefix__c;}

    result = URL_Prefix;
    
    return result;
  }


//******************
//Test Method 
//******************
  static testMethod void TestMe() {
    System.debug(Retrieve_URL_Prefix());
    System.debug(Retrieve_URL_Prefix());
    System.debug(Retrieve_URL_Prefix());
  }

//The End
}

 
This is definately not the most elegant solution to handle this, but it definately beats hard coding anything.  I perform the call to Retrieve_URL_Prefix a couple of times in the test method so that I can confim multiple calls will only run the SOQL query one time.
 
The good thing about this, is that down the road, if there is other system criteria the is different between sandbox and production, I can add additional fields to the table and use another method to retrieve the info here.  Also, if/when APEX gains the ability to get this information itself, I can just change this method to get the information an alternate way, get rid of the custom object if it's no longer needed, and all of my other code that depends on this call will still work.
 
Jon Keener
sfdcfoxsfdcfox

Unless you're sending an email, it doesn't matter what server you are on. Just use a link like this:

oppLink = "/{!Opportunity.Id}"

The browser will automatically figure out what server you're on...

Jon KeenerJon Keener

Totally agree.  In our case, we were sending an email, which is why I had to resort to the above.

Jon Keener

jhkeener@ashland.com

TehNrdTehNrd
sfdcfox,

I am familiar with that method but it does not work in my scenario. What I am doing is building the body of an Activity and in this text there are hyperlinks to related records in salesforce.com. Therefore I need to code the entire URL.

Even Jon's method requires "hardcoding" the value. Not in code but still in a custom object. For packaged apps this won't scale well. A system method is really required for this.


Jon KeenerJon Keener

I definately didn't like to hard code it, even in a custom object, but it was the only solution I could find.

From a packaging perspective, you could include an s-control to create the record in the table.  From an s-control previously, I was able to substring the API URL to get to the Salesforce Instance I was on.

Below is a snippet of javascript code from an s-control.  Doesn't do anywhere near what it would need to do in this instance, but you should get the idea.  Assuming you were packaging this up, it would just be a requirement that the s-control was ran immediately after installation of the package to a new environment.

Code:
var APIURL = "{!API.Partner_Server_URL_90}";

if (APIURL.substring(0,12) == 'https://tapp') SFEnv = 'SANDBOX';
if (APIURL.substring(0,12) != 'https://tapp') SFEnv = 'PRODUCTION';

I definately think a function needs to be added to APEX to obtain this information, and once something is added, I plan to switch to it.  But for now, I'm not sure if there is a better option than what's here.....

Jon Keener

jhkeener@ashland.com
 

sfdcfoxsfdcfox
Okay, that makes sense. This should probably head on over to the IdeaExchange so it's properly documented as a request.
Execute EZSAASExecute EZSAAS
Jason - if you prepare your link as this: https://login.salesforce.com/?startURL=OBJECT.Id
then first time user clicks on this link in email, user will be prompted to login and force.com will figure out the instance and redirect the user appropriately. Subsequent clicks will directly take the user to correct object as long as there is a valid session.
It may not work for sandboxes!
TehNrdTehNrd
FYI,

http://ideas.salesforce.com/article/show/10091004/Apex_method_to_identify_salesforcecom_server
This was selected as the best answer
ctjrctjr

Execute EZSAAS wrote:
Jason - if you prepare your link as this: https://login.salesforce.com/?startURL=OBJECT.Id
then first time user clicks on this link in email, user will be prompted to login and force.com will figure out the instance and redirect the user appropriately. Subsequent clicks will directly take the user to correct object as long as there is a valid session.
It may not work for sandboxes!




Thanks for the tip - this is exactly what I need to do.

However, I'm being redirected to https://na2.salesforce.com/secur/006ABCDEC... and getting an error (for first and subsequent clicks.) If I remove /secur/ from my redirected url, all is well. Any ideas?
ctjrctjr
Turns out a leading slash fixed my last issue:

https://login.salesforce.com/?startURL=/OBJECT.Id redirects properly.

Unfortunately, now I'm being asked to log in each time. Subsequent visits do NOT recognize that I'm already authenticated. I've verified this behavior in both sandbox and production environments.
Ron HessRon Hess
I think you can get this from ApexPage method geturl()

ApexPages.currentPage().getUrl();

TehNrdTehNrd
I just tried that it appears to only return the values after the .com

-Jason
Ron HessRon Hess
right you are, i was mistaken.

i'll keep looking for a method to do this
XactiumBenXactiumBen
In a visualforce page, I have been using the following:

Code:
ApexPages.getCurrentPage().getHeaders().get('Host');

 
This seems to get my Instance.  The only problem is this doesn't work on standard salesforce pages (I also need to add https:// to the start of the value I get as well).
Scott.MScott.M
I ran into the same problem with the Google API. One of the parameters for the AuthSubUtil.getRequestUrl() function is the host name. I had to hard code it which makes me very uncomfortable since an organization can change hosts at any time. I really don't want to have to take an extra trip to the browser and back to get it using Javascript :) you would think it should be straight forward to add a System.getHostName() function.


ApexPages.getCurrentPage().getHeaders().get('Host'); works :)  thanks XactiumBen


Message Edited by Scott.M on 09-26-2008 07:02 AM
Ron HessRon Hess
Nice!
TehNrdTehNrd
Hmm...... so I am trying to use this in a webservice and its not working:

string host = ApexPages.CurrentPage().getHeaders().get('Host');

Returns a null pointer exception. I guess this makes sense as this is a webservice and there isn't really a current page. I guess this is just more of a reason for there to be an apex method that returns this value.
Scott.MScott.M
That's a good point. It worked in my context because it was a visualforce page. Could you fudge it by creating a dummy visualforce page and then getting the host from the page reference even though you never use it. Something like Page.dummyPage.getHeaders().get('Host'). Not ideal but better than hard coding? Voted for your idea for an apex function :)


TehNrdTehNrd
Good idea but it doesn't appear to work.

Code:
PageReference dummy = new PageReference('/');
String host = dummy.getHeaders().get('Host');
system.debug('host: ' + host);

Debug:
line 27, column 9: host: null

 

XactiumBenXactiumBen
I don't think it will populate your headers until you navigate to that specific page.  And since you can't use the ApexPages namespace/class or whatever it is in a context other than a visualforce page I'd say getting the salesforce instance in Apex that's not a visualforce controller is next to impossible.

I tried various attempts in a trigger with very little success. 
jhartjhart
I just posted a method (in another thread) of a way that gets this value for all Apex code contexts.