Unstable getting results from CiscoProvider.GetCall(int callLegID) - jtapi

I have code:
CiscoJtapiPeer peer = (CiscoJtapiPeer) JtapiPeerFactory.getJtapiPeer(null);
CiscoProvider provider = (CiscoProvider) peer.getProvider(host+";login="+ login +";passwd=" + pass);
provider.addObserver(new ProviderObserver() {
#Override
public void providerChangedEvent (ProvEv [] eventList) {
if (eventList == null) return;
for (int i = 0; i < eventList.length; ++i) {
if (eventList[i] instanceof ProvInServiceEv) {
inService.set();
}
}
}
});
inService.waitTrue();
System.out.println("In servise.");
CiscoAddress srcAddr = (CiscoAddress) provider.getAddress(dn);
srcAddr.addCallObserver(new MyCallControlCallObserver(dn, provider))
and observer on address:
#Override
public void callChangedEvent(CallEv[] evlist)throws Exception{
for (CallEv evlist1 : evlist) {
if (evlist1.getID() == CiscoTermConnRecordingEndEv.ID) {
call = provider.getCall(callid);
if (call != null) {
System.out.println("From: " + call.getCallingAddress() + " To: " + call.getCalledAddress());
}
else {System.out.println("Call is null");}
}
}
}
function provider.getCall(callid) returns the object is not stable. Like this -
From: 4403 To: 5215
Call is null
Call is null
From: 4403 To: 5215
From: 4403 To: 5215
Call is null
Call is null
From: 4403 To: 5215
The interval between calls 5 - 15 seconds and the duration of 3 - 7 seconds. I tried to change to handle the event - the same result.
What am i doing wrong? Maybe it's due to the fact that the CUCM is a cluster? And CiscoProvider is different for each call?

if (evlist1.getID() == CiscoTermConnRecordingEndEv.ID) {
call = provider.getCall(callid);
if (call != null) {
System.out.println("From: " + call.getCallingAddress() + " To: " + call.getCalledAddress());
}
else {System.out.println("Call is null");}
}
You are getting calls which has recording option true. You get only RECORDED calls. Thats why your function is not stable. If you want get all calls instead of CiscoTermConnRecordingEndEv use TermConnActiveEv if you want get call in active state or TermConnRingingEv if you want get call in ringing state.

Related

Use Cecil to insert begin/end block around functions

this simple code works fine and allows to add a BeginSample/EndSample call around each Update/LateUpdate/FixedUpdate function. However it doesn't take in consideration early return instructions, for example as result of a condition. Do you know how to write a similar function that take in considerations early returns so that the EndSample call will be executed under every circumstance?
Note that I am not a Cecil expert, I am just learning now. It appears to me that Cecil automatically updates the operations that returns early after calling InsertBefore and similar functions. So if a BR opcode was previously jumping to a specific instruction address, the address will be updated after the insertions in order to jump to the original instruction. This is OK in most of the cases, but in my case it means that an if statement would skip the last inserted operation as the BR operation would still point directly to the final Ret instruction. Note that Update, LateUpdate and FixedUpdate are all void functions.
foreach (var method in type.Methods)
{
if ((method.Name == "Update" || method.Name == "LateUpdate" || method.Name == "FixedUpdate") &&
method.HasParameters == false)
{
var beginMethod =
module.ImportReference(typeof (Profiler).GetMethod("BeginSample",
new[] {typeof (string)}));
var endMethod =
module.ImportReference(typeof (Profiler).GetMethod("EndSample",
BindingFlags.Static |
BindingFlags.Public));
Debug.Log(method.Name + " method found in class: " + type.Name);
var ilProcessor = method.Body.GetILProcessor();
var first = method.Body.Instructions[0];
ilProcessor.InsertBefore(first,
Instruction.Create(OpCodes.Ldstr,
type.FullName + "." + method.Name));
ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Call, beginMethod));
var lastRet = method.Body.Instructions[method.Body.Instructions.Count - 1];
ilProcessor.InsertBefore(lastRet, Instruction.Create(OpCodes.Call, endMethod));
changed = true;
}
}
as a Bonus, if you can explain to me the difference between Emit and Append a newly created instruction with the same operand. does Append execute an Emit under the hood or does something more?
I may have found the solution, at least apparently it works. I followed the code used to solve a similar problem from here:
https://groups.google.com/forum/#!msg/mono-cecil/nE6JBjvEFCQ/MqV6tgDCB4AJ
I adapted it for my purposes and it seemed to work, although I may find out other issues. This is the complete code:
static bool ProcessAssembly(AssemblyDefinition assembly)
{
var changed = false;
var moduleG = assembly.MainModule;
var attributeConstructor =
moduleG.ImportReference(
typeof(RamjetProfilerPostProcessedAssemblyAttribute).GetConstructor(Type.EmptyTypes));
var attribute = new CustomAttribute(attributeConstructor);
var ramjet = moduleG.ImportReference(typeof(RamjetProfilerPostProcessedAssemblyAttribute));
if (assembly.HasCustomAttributes)
{
var attributes = assembly.CustomAttributes;
foreach (var attr in attributes)
{
if (attr.AttributeType.FullName == ramjet.FullName)
{
Debug.LogWarning("<color=yellow>Skipping already-patched assembly:</color> " + assembly.Name);
return false;
}
}
}
assembly.CustomAttributes.Add(attribute);
foreach (var module in assembly.Modules)
{
foreach (var type in module.Types)
{
// Skip any classes related to the RamjetProfiler
if (type.Name.Contains("AssemblyPostProcessor") || type.Name.Contains("RamjetProfiler"))
{
// Todo: use actual type equals, not string matching
Debug.Log("Skipping self class : " + type.Name);
continue;
}
if (type.BaseType != null && type.BaseType.FullName.Contains("UnityEngine.MonoBehaviour"))
{
foreach (var method in type.Methods)
{
if ((method.Name == "Update" || method.Name == "LateUpdate" || method.Name == "FixedUpdate") &&
method.HasParameters == false)
{
var beginMethod =
module.ImportReference(typeof(Profiler).GetMethod("BeginSample",
new[] { typeof(string) }));
var endMethod =
module.ImportReference(typeof(Profiler).GetMethod("EndSample",
BindingFlags.Static |
BindingFlags.Public));
Debug.Log(method.Name + " method found in class: " + type.Name);
var ilProcessor = method.Body.GetILProcessor();
var first = method.Body.Instructions[0];
ilProcessor.InsertBefore(first,
Instruction.Create(OpCodes.Ldstr,
type.FullName + "." + method.Name));
ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Call, beginMethod));
var lastcall = Instruction.Create(OpCodes.Call, endMethod);
FixReturns(method, lastcall);
changed = true;
}
}
}
}
}
return changed;
}
static void FixReturns(MethodDefinition med, Instruction lastcall)
{
MethodBody body = med.Body;
var instructions = body.Instructions;
Instruction formallyLastInstruction = instructions[instructions.Count - 1];
Instruction lastLeaveInstruction = null;
var lastRet = Instruction.Create(OpCodes.Ret);
instructions.Add(lastcall);
instructions.Add(lastRet);
for (var index = 0; index < instructions.Count - 1; index++)
{
var instruction = instructions[index];
if (instruction.OpCode == OpCodes.Ret)
{
Instruction leaveInstruction = Instruction.Create(OpCodes.Leave, lastcall);
if (instruction == formallyLastInstruction)
{
lastLeaveInstruction = leaveInstruction;
}
instructions[index] = leaveInstruction;
}
}
FixBranchTargets(lastLeaveInstruction, formallyLastInstruction, body);
}
private static void FixBranchTargets(
Instruction lastLeaveInstruction,
Instruction formallyLastRetInstruction,
MethodBody body)
{
for (var index = 0; index < body.Instructions.Count - 2; index++)
{
var instruction = body.Instructions[index];
if (instruction.Operand != null && instruction.Operand == formallyLastRetInstruction)
{
instruction.Operand = lastLeaveInstruction;
}
}
}
basically what it does is to add a Ret instuction, but then replace all the previous Ret (usually one, why should it be more than one?) with a Leave function (don't even know what it means :) ), so that all the previous jumps remain valid. Differently than the original code, I make the Leave instruction point to the EndSample call before the last Ret

How to avoid to fetch a list of followers of the same Twitter user that was displayed before

I'm very new at coding and I'm having some issues. I'd like to display the followers of followers of ..... of followers of some specific users in Twitter. I have coded this and I can set a limit for the depth. But, while running the code with a small sample, I saw that I run into the same users again and my code re-display the followers of these users. How can I avoid this and skip to the next user? You can find my code below:
By the way, while running my code, I encounter with a 401 error. In the list I'm working on, there's a private user, and when my code catches that user, it stops. Additionally, how can I deal with this issue? I'd like to skip such users and prevent my code to stop.
Thank you for your help in advance!
PS: I know that I'll encounter with a 429 error working with a large sample. After fixing these issues, I'm planning to review relevant discussions to deal with.
public class mainJava {
public static Twitter twitter = buildConfiguration.getTwitter();
public static void main(String[] args) throws Exception {
ArrayList<String> rootUserIDs = new ArrayList<String>();
Scanner s = new Scanner(new File("C:\\Users\\ecemb\\Desktop\\rootusers1.txt"));
while (s.hasNextLine()) {
rootUserIDs.add(s.nextLine());
}
s.close();
for (String rootUserID : rootUserIDs) {
User rootUser = twitter.showUser(rootUserID);
List<User> userList = getFollowers(rootUser, 0);
}
}
public static List<User> getFollowers(User parent, int depth) throws Exception {
List<User> userList = new ArrayList<User>();
if (depth == 2) {
return userList;
}
IDs followerIDs = twitter.getFollowersIDs(parent.getScreenName(), -1);
long[] ids = followerIDs.getIDs();
for (long id : ids) {
twitter4j.User child = twitter.showUser(id);
userList.add(child);
getFollowers(child, depth + 1);
System.out.println(depth + "th user: " + parent.getScreenName() + " Follower: " + child.getScreenName());
}
return userList;
}
}
I guess graph search algorithms can be implemented for this particular issue. I chose Breadth First Search algorithm because visiting root user's followers at first would be better. You can check this link to additional information about algorithm.
Here is my implementation for your problem:
public List<User> getFollowers(User parent, int startDepth, int finalDepth) {
List<User> userList = new ArrayList<User>();
Queue<Long> queue = new LinkedList<Long>();
HashMap<Long, Integer> discoveredUserId = new HashMap<Long, Integer>();
try {
queue.add(parent.getId());
discoveredUserId.put(parent.getId(), 0);
while (!queue.isEmpty()) {
long userId = queue.remove();
int discoveredDepth = discoveredUserId.get(userId);
if (discoveredDepth == finalDepth) {
continue;
}
User user = twitter.showUser(userId);
handleRateLimit(user.getRateLimitStatus());
if (user.isProtected()) {
System.out.println(user.getScreenName() + "'s account is protected. Can't access followers.");
continue;
}
IDs followerIDs = null;
followerIDs = twitter.getFollowersIDs(user.getScreenName(), -1);
handleRateLimit(followerIDs.getRateLimitStatus());
long[] ids = followerIDs.getIDs();
for (int i = 0; i < ids.length; i++) {
if (!discoveredUserId.containsKey(ids[i])) {
discoveredUserId.put(ids[i], discoveredDepth + 1);
User child = twitter.showUser(ids[i]);
handleRateLimit(child.getRateLimitStatus());
userList.add(child);
if (discoveredDepth >= startDepth && discoveredDepth < finalDepth) {
System.out.println(discoveredDepth + ". user: " + user.getScreenName() + " has " + user.getFollowersCount() + " follower(s) " + (i + 1) + ". Follower: " + child.getScreenName());
}
queue.add(ids[i]);
} else {//prints to console but does not check followers. Just for data consistency
User child = twitter.showUser(ids[i]);
handleRateLimit(child.getRateLimitStatus());
if (discoveredDepth >= startDepth && discoveredDepth < finalDepth) {
System.out.println(discoveredDepth + ". user: " + user.getScreenName() + " has " + user.getFollowersCount() + " follower(s) " + (i + 1) + ". Follower: " + child.getScreenName());
}
}
}
}
} catch (TwitterException e) {
e.printStackTrace();
}
return userList;
}
//There definitely are more methods for handling rate limits but this worked for me well
private void handleRateLimit(RateLimitStatus rateLimitStatus) {
//throws NPE here sometimes so I guess it is because rateLimitStatus can be null and add this conditional expression
if (rateLimitStatus != null) {
int remaining = rateLimitStatus.getRemaining();
int resetTime = rateLimitStatus.getSecondsUntilReset();
int sleep = 0;
if (remaining == 0) {
sleep = resetTime + 1; //adding 1 more second
} else {
sleep = (resetTime / remaining) + 1; //adding 1 more second
}
try {
Thread.sleep(sleep * 1000 > 0 ? sleep * 1000 : 0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
in this code HashMap<Long, Integer> discoveredUserId is used to prevent program checking same users repeatedly and storing in which depth we faced with this user.
and for private users, there is isProtected() method in twitter4j library.
Hope this implementation helps.

Sales force EMP connector, stops receiving notification after some time

I am performing a POC to check Streaming API stability, POC is as follows
Program 1 : subscribe to pushtopic created against Account object
Program 2 : create, update & delete single record after every 10 min interval
Both this programs were kept running for more than 12 hours (left overnight), after that I verified if all notification are received or not and found that after sometime (in this case it was nearly ~ 2 hours 45 min ) no notification were received, I repeated this twice and both case it stops getting notification after sometime.
Test code used
Streaming API client (using EMP connector)
public class SFPoc {
static Long count = 0L;
static Long Leadcount = 0L;
public static void main(String[] argv) throws Exception {
String userName = "<user_name>";
String password = "<pwd>";
String pushTopicName = "/topic/AccountPT";
String pushTopicNameLead = "/topic/Leadwhere";
long replayFrom = EmpConnector.REPLAY_FROM_EARLIEST;
String securityToken = "<token>";
BayeuxParameters custom = getBayeuxParamWithSpecifiedAPIVersion("37.0");
BayeuxParameters params = null;
try {
params = login(userName, password + securityToken, custom);
} catch (Exception e) {
e.printStackTrace();
}
Consumer<Map<String, Object>> consumer = event -> System.out.println(String.format("Received:\n%s ** Recieved at %s, event count total %s", event, LocalDateTime.now() , ++count));
Consumer<Map<String, Object>> consumerLead = event -> System.out.println(String.format("****** LEADS ***** Received:\n%s ** Recieved at %s, event count total %s", event, LocalDateTime.now() , ++Leadcount));
EmpConnector connector = new EmpConnector(params);
connector.start().get(10, TimeUnit.SECONDS);
TopicSubscription subscription = connector.subscribe(pushTopicName, replayFrom, consumer).get(10, TimeUnit.SECONDS);
TopicSubscription subscriptionLead = connector.subscribe(pushTopicNameLead, replayFrom, consumerLead).get(10, TimeUnit.SECONDS);
System.out.println(String.format("Subscribed: %s", subscription));
System.out.println(String.format("Subscribed: %s", subscriptionLead));
}
private static BayeuxParameters getBayeuxParamWithSpecifiedAPIVersion(String apiVersion) {
BayeuxParameters params = new BayeuxParameters() {
#Override
public String version() {
return apiVersion;
}
#Override
public String bearerToken() {
return null;
}
};
return params;
}
}
Code which is doing record create/update/delete periodically to generate events
import com.sforce.soap.enterprise.*;
import com.sforce.soap.enterprise.Error;
import com.sforce.soap.enterprise.sobject.Account;
import com.sforce.soap.enterprise.sobject.Contact;
import com.sforce.ws.ConnectionException;
import com.sforce.ws.ConnectorConfig;
import java.time.LocalDateTime;
public class SFDCDataAdjustment {
static final String USERNAME = "<username>";
static final String PASSWORD = "<pwd&securitytoken>";
static EnterpriseConnection connection;
static Long count = 0L;
public static void main(String[] args) {
ConnectorConfig config = new ConnectorConfig();
config.setUsername(USERNAME);
config.setPassword(PASSWORD);
//config.setTraceMessage(true);
try {
connection = Connector.newConnection(config);
// display some current settings
System.out.println("Auth EndPoint: "+config.getAuthEndpoint());
System.out.println("Service EndPoint: "+config.getServiceEndpoint());
System.out.println("Username: "+config.getUsername());
System.out.println("SessionId: "+config.getSessionId());
// run the different examples
while (true) {
createAccounts();
updateAccounts();
deleteAccounts();
Thread.sleep(1 * 10 * 60 * 1000);
}
} catch (ConnectionException e1) {
e1.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// queries and displays the 5 newest contacts
private static void queryContacts() {
System.out.println("Querying for the 5 newest Contacts...");
try {
// query for the 5 newest contacts
QueryResult queryResults = connection.query("SELECT Id, FirstName, LastName, Account.Name " +
"FROM Contact WHERE AccountId != NULL ORDER BY CreatedDate DESC LIMIT 5");
if (queryResults.getSize() > 0) {
for (int i=0;i<queryResults.getRecords().length;i++) {
// cast the SObject to a strongly-typed Contact
Contact c = (Contact)queryResults.getRecords()[i];
System.out.println("Id: " + c.getId() + " - Name: "+c.getFirstName()+" "+
c.getLastName()+" - Account: "+c.getAccount().getName());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
// create 5 test Accounts
private static void createAccounts() {
System.out.println("Creating a new test Account...");
Account[] records = new Account[1];
try {
// create 5 test accounts
for (int i=0;i<1;i++) {
Account a = new Account();
a.setName("OptyAccount "+i);
records[i] = a;
}
// create the records in Salesforce.com
SaveResult[] saveResults = connection.create(records);
// check the returned results for any errors
for (int i=0; i< saveResults.length; i++) {
if (saveResults[i].isSuccess()) {
System.out.println(i+". Successfully created record - Id: " + saveResults[i].getId() + "At " + LocalDateTime.now());
System.out.println("************Event Count************" + ++count);
} else {
Error[] errors = saveResults[i].getErrors();
for (int j=0; j< errors.length; j++) {
System.out.println("ERROR creating record: " + errors[j].getMessage());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
// updates the 5 newly created Accounts
private static void updateAccounts() {
System.out.println("Update a new test Accounts...");
Account[] records = new Account[1];
try {
QueryResult queryResults = connection.query("SELECT Id, Name FROM Account ORDER BY " +
"CreatedDate DESC LIMIT 1");
if (queryResults.getSize() > 0) {
for (int i=0;i<queryResults.getRecords().length;i++) {
// cast the SObject to a strongly-typed Account
Account a = (Account)queryResults.getRecords()[i];
System.out.println("Updating Id: " + a.getId() + " - Name: "+a.getName());
// modify the name of the Account
a.setName(a.getName()+" -- UPDATED");
records[i] = a;
}
}
// update the records in Salesforce.com
SaveResult[] saveResults = connection.update(records);
// check the returned results for any errors
for (int i=0; i< saveResults.length; i++) {
if (saveResults[i].isSuccess()) {
System.out.println(i+". Successfully updated record - Id: " + saveResults[i].getId() + "At " + LocalDateTime.now());
System.out.println("************Event Count************" + ++count);
} else {
Error[] errors = saveResults[i].getErrors();
for (int j=0; j< errors.length; j++) {
System.out.println("ERROR updating record: " + errors[j].getMessage());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
// delete the 5 newly created Account
private static void deleteAccounts() {
System.out.println("Deleting new test Accounts...");
String[] ids = new String[1];
try {
QueryResult queryResults = connection.query("SELECT Id, Name FROM Account ORDER BY " +
"CreatedDate DESC LIMIT 1");
if (queryResults.getSize() > 0) {
for (int i=0;i<queryResults.getRecords().length;i++) {
// cast the SObject to a strongly-typed Account
Account a = (Account)queryResults.getRecords()[i];
// add the Account Id to the array to be deleted
ids[i] = a.getId();
System.out.println("Deleting Id: " + a.getId() + " - Name: "+a.getName());
}
}
// delete the records in Salesforce.com by passing an array of Ids
DeleteResult[] deleteResults = connection.delete(ids);
// check the results for any errors
for (int i=0; i< deleteResults.length; i++) {
if (deleteResults[i].isSuccess()) {
System.out.println(i+". Successfully deleted record - Id: " + deleteResults[i].getId() + "At " + LocalDateTime.now());
System.out.println("************Event Count************" + ++count);
} else {
Error[] errors = deleteResults[i].getErrors();
for (int j=0; j< errors.length; j++) {
System.out.println("ERROR deleting record: " + errors[j].getMessage());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Further updates got below mentioned error after which notification were
2017-03-09T19:30:28.346 ERROR [com.salesforce.emp.connector.EmpConnector] - connection failure, reconnecting
org.cometd.common.TransportException: {httpCode=503}
at org.cometd.client.transport.LongPollingTransport$2.onComplete(LongPollingTransport.java:278)
at org.eclipse.jetty.client.ResponseNotifier.notifyComplete(ResponseNotifier.java:193)
After this reconnect also happened and handshake also happened but error seems to be in resubscribe() EMP connector seems to be not able to resubscribe for some reason
Note I am using "resubscribe-on-disconnect" branch of EMP connetor
We have determined there was a bug on the server side in a 403 case. The Streaming API uses a session routing cookie and this cookie periodically expires. When it expires, the session is routed to another server, and this responds with a 403. In the current version, this 403 response does not include connect advice, and the client does not attempt to reconnect. This has been fixed and the fix is currently live. My understanding is that this should fix the reconnect problem exhibited by the clients.

Player should win when all objects are collected

I have a simple game where the player needs to collect 4 game objects within 30 sec. Now I already created the timer, so I need to let the game know that if all game objects are collected under the time limit the player wins.
This is my code so far:
using UnityEngine;
using System.Collections;
public class GameState : MonoBehaviour
{
public static int count = 0;
public float seconds = 30;
public float minutes = 0;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
if (seconds <= 0)
{
seconds = 30;
if (minutes >= 1)
{
minutes -- ;
}
else
{
minutes = 0;
seconds = 0;
GameObject.Find("TimerText").guiText.text = minutes.ToString("f0") + ":0" + seconds.ToString("f0");
}
}
else
{
seconds -= Time.deltaTime;
}
if (Mathf.Round(seconds) <=9)
{
GameObject.Find("TimerText").guiText.text = minutes.ToString("f0") + ":0" + seconds.ToString("f0");
}
else
{
GameObject.Find("TimerText").guiText.text = minutes.ToString("f0") + ":" + seconds.ToString("f0");
}
if(count >= 1)
{
print("You Won!");
}
}
void OnTriggerEnter(Collider collide)
{
if (collide.transform.tag == "Cube")
{
count = count + 1;
Destroy (collide.gameObject);
}
}
}
Note: cube is one of the game object that needs to be picked up.
you could interrupt the game or show a victory menu or something when you have all the cubes collected
void Update ()
{
bool cubescollected = false;
if(cubescollected == 4)
{
ShowVictoryOrSomething();
cubescollected = true
}
if(cubescollected == true)
return;
... your timer code
}
good luck and happy coding

How to disable/deactivate a SalesForce User through SOAP API?

I want to disable a User programmetically by using SOAP API. How can I do that? I am using Partner API and I have Developer edition. I have manage users persmissions set. I have gone through this link. I am looking for code which can help me disable/deactivate a User.
This is my code:
import com.sforce.soap.partner.Connector;
import com.sforce.soap.partner.PartnerConnection;
import com.sforce.soap.partner.QueryResult;
import com.sforce.soap.partner.sobject.SObject;
import com.sforce.ws.ConnectionException;
import com.sforce.ws.ConnectorConfig;
public class DeactivateUser {
public static void main(String[] args) {
ConnectorConfig config = new ConnectorConfig();
config.setUsername("waprau#waprau.com");
config.setPassword("sjjhggrhgfhgffjdgj");
PartnerConnection connection = null;
try {
connection = Connector.newConnection(config);
QueryResult queryResults = connection.query("SELECT Username, IsActive from User");
if (queryResults.getSize() > 0) {
for (SObject s : queryResults.getRecords()) {
if(s.getField("Username").equals("abcd#pqrs.com")){
System.out.println("Username: " + s.getField("Username"));
s.setField("IsActive", false);
}
System.out.println("Username: " + s.getField("Username") + " IsActive: " + s.getField("IsActive"));
}
}
} catch (ConnectionException ce) {
ce.printStackTrace();
}
}
}
This is output:
Username: waprau#waprau.com IsActive: true
Username: jsmith#ymail.net IsActive: false
Username: abcd#pqrs.com
Username: abcd#pqrs.com IsActive: false
However in UI when I go to My Name > Setup > Manage Users > Users, it always show 'Active' check box for user abcd#pqrs.com selected :-(
It doesn't look like you're actually sending the update back to Salesforce - you're just setting IsActive to false locally. You will need to use a call to PartnerConnection.update(SObject[] sObjects) in order for Salesforce to reflect your changes, like so:
try {
connection = Connector.newConnection(config);
QueryResult queryResults = connection.query("SELECT Id, Username, IsActive from User");
if ( queryResults.getSize() > 0 ) {
// keep track of which records you want to update with an ArrayList
ArrayList<SObject> updateObjects = new ArrayList<SObject>();
for (SObject s : queryResults.getRecords()) {
if ( s.getField("Username").equals("abcd#pqrs.com") ){
System.out.println("Username: " + s.getField("Username"));
s.setField("Id", null);
s.setField("IsActive", false);
}
updateObjects.add(s); // if you want to update all records...if not, put this in a conditional statement
System.out.println("Username: " + s.getField("Username") + " IsActive: " + s.getField("IsActive"));
}
// make the update call to Salesforce and then process the SaveResults returned
SaveResult[] saveResults = connection.update(updateObjects.toArray(new SObject[updateObjects.size()]));
for ( int i = 0; i < saveResults.length; i++ ) {
if ( saveResults[i].isSuccess() )
System.out.println("record " + saveResults[i].getId() + " was updated successfully");
else {
// There were errors during the update call, so loop through and print them out
System.out.println("record " + saveResults[i].getId() + " failed to save");
for ( int j = 0; j < saveResults[i].getErrors().length; j++ ) {
Error err = saveResults[i].getErrors()[j];
System.out.println("error code: " + err.getStatusCode().toString());
System.out.println("error message: " + err.getMessage());
}
}
}
}
} catch (ConnectionException ce) {
ce.printStackTrace();
}
It is possible to directly work with the user record without the SOQL query if you already know the Id.
SalesforceSession session = ...;
sObject userSObject = new sObject();
userSObject.Id = "00570000001V9NA";
userSObject.type = "User";
userSObject.Any = new System.Xml.XmlElement[1];
XmlDocument xmlDocument = new XmlDocument();
XmlElement fieldXmlElement = xmlDocument.CreateElement("IsActive");
fieldXmlElement.InnerText = bool.FalseString;
userSObject.Any[0] = fieldXmlElement;
SaveResult[] result = session.Binding.update(new sObject[] { userSObject });
foreach(SaveResult sr in result)
{
System.Diagnostics.Debug.WriteLine(sr.success + " " + sr.id);
if(!sr.success)
{
foreach(Error error in sr.errors)
{
System.Diagnostics.Debug.WriteLine(error.statusCode + " " + error.message);
}
}
}