Flow: Use new type for variable? - salesforce

I have a simple new class X which holds some results of a callout to an external system.
In a flow I need a variable of type X. Is there any way to declare a variable of that new type in a flow?
My new class is:
public class FooCalloutResult {
public Boolean success;
public Map<Id, Boolean> results;
public List<String> messages;
public FooCalloutResult() {
success = false;
results = new Map<Id, Boolean>();
messages = new List<String>();
}
}

If you want to get some data in a flow from an apex class you need to have an Process Invocable method - this is done by adding the #InvocableMethod annotation.
Example:
global class lookUpAccountAnnotation {
#InvocableMethod
public static List<String> getAccountIds(List<String> names) {
List<Id> accountIds = new List<Id>();
List<Account> accounts = [SELECT Id FROM Account WHERE Name in :names];
for (Account account : accounts) {
accountIds.add(account.Id);
}
return accountIds;
}
}
With this annotation the class will appear in your list of available elements in the Flow and you need to put the Input and Output that will go into it.
Depending on what kind of operation you want to do you might need to use the Process.plugin interface instead. Please check this article to see which option supports what kind of data to decide on what you need - https://help.salesforce.com/articleView?id=vpm_designer_elements_apex.htm&type=5

Related

How to use dynamic schema in spring data with mongodb?

Mongodb is a no-schema document database, but in spring data, it's necessary to define entity class and repository class, like following:
Entity class:
#Document(collection = "users")
public class User implements UserDetails {
#Id private String userId;
#NotNull #Indexed(unique = true) private String username;
#NotNull private String password;
#NotNull private String name;
#NotNull private String email;
}
Repository class:
public interface UserRepository extends MongoRepository<User, String> {
User findByUsername(String username);
}
Is there anyway to use map not class in spring data mongodb so that the server can accept any dynamic JSON data then store it in BSON without any pre-class define?
First, a few insightful links about schemaless data:
what does “schemaless” even mean anyway?
“schemaless” doesn't mean “schemafree”
Second... one may wonder if Spring, or Java, is the right solution for your problem - why not a more dynamic tool, such a Ruby, Python or the Mongoshell?
That being said, let's focus on the technical issue.
If your goal is only to store random data, you could basically just define your own controller and use the MongoDB Java Driver directly.
If you really insist on having no predefined schema for your domain object class, use this:
#Document(collection = "users")
public class User implements UserDetails {
#Id
private String id;
private Map<String, Object> schemalessData;
// getters/setters omitted
}
Basically it gives you a container in which you can put whatever you want, but watch out for serialization/deserialization issues (this may become tricky if you had ObjectIds and DBRefs in your nested document). Also, updating data may become nasty if your data hierarchy becomes too complex.
Still, at some point, you'll realize your data indeed has a schema that can be pinpointed and put into well-defined POJOs.
Update
A late update since people still happen to read this post in 2020: the Jackson annotations JsonAnyGetter and JsonAnySetter let you hide the root of the schemaless-data container so your unknown fields can be sent as top-level fields in your payload. They will still be stored nested in your MongoDB document, but will appear as top-level fields when the ressource is requested through Spring.
#Document(collection = "users")
public class User implements UserDetails {
#Id
private String id;
// add all other expected fields (getters/setters omitted)
private String foo;
private String bar;
// a container for all unexpected fields
private Map<String, Object> schemalessData;
#JsonAnySetter
public void add(String key, Object value) {
if (null == schemalessData) {
schemalessData = new HashMap<>();
}
schemalessData.put(key, value);
}
#JsonAnyGetter
public Map<String, Object> get() {
return schemalessData;
}
// getters/setters omitted
}

What is the design pattern name that used to create an object by passing an engine object

I have a class called DatabaseModel.
And an interface called DatabaseEngineInterface that have a methods such as:
insert
update
delete
select
So I can on running time determine which engine to use mysql or oracle which are a classes that implements the DatabaseEngineInterface
EngineDatabase engine = new MySQLEngine();
DatabaseModel db = new DatabaseModel(engine);
What is this design pattern called?
Specifically, this is the Constructor Injection pattern (described in my book), which is a special case of the Strategy pattern.
Isn't it an implementation of the strategy pattern? Wikipedia states that the strategy pattern is:
>a software design pattern that enables an algorithm's behavior to be selected at runtime
It also says that the strategy pattern:
defines a family of algorithms,
encapsulates each algorithm, and
makes the algorithms interchangeable within that family.
You are allowing the database which will be used (and so the behaviour) to be selected at run time. You have defined a family of algorithms (your interface), encapsulated each algorithm (by creating a class per provider) and they can be used interchangeably as the DatabaseModel depends only on the interface.
DaoFactory design pattern fits well for your implementation.
Interface
public interface DatabaseEngineInterface {
public void insert(User user);
public void update(User user);
public void delete(int userId);
}
Class which implements the above methods:
public class DatabaseModel implements DatabaseEngineInterface {
#Override
public void delete(int userId) {
// delete user from user table
}
#Override
public User[] findAll() {
// get a list of all users from user table
return null;
}
#Override
public User findByKey(int userId) {
// get a user information if we supply unique userid
return null;
}
#Override
public void insert(User user) {
// insert user into user table
}
#Override
public void update(User user) {
// update user information in user table
}
}
Factory
public class DatabaseModelDAOFactory {
public static UserDAO getUserDAO(String type) {
if (type.equalsIgnoreCase("mysql")) {
return new UserDAOMySQLImpl();
} else {
return new UserDAOORACLEImpl();
}
}
}
Client side code:
Then, in the client side instead of a hardcoded line like:
DatabaseModel userDAO=DatabaseModelDAOFactory.getUserDAODatabaseEngineInterface("jdbc");
You could have a properties file to be able to switch between DAOs dynamically, having retrieved that string from the properties file you can simply do:
DatabaseModel userDAO=DatabaseModelDAOFactory.getUserDaoDatabaseEngineInterface(myStringFromPropertiesFile);
myStringFromPropertiesFile would contain "mysql" or "oracle" according to the definition in your properties file.

Strings sometimes not retrieved with Cloud Datastore query (GAE, JDO, Endpoints, Java)

I have a problem with retrieving objects from Google Cloud Datastore using JDO. It is incredibly frustrating, because 99.5% of the time my code works perfectly, but 0.5% of the time some of the data is missing, and I can't find consistent steps to replicate the bug. I'm fairly certain that my issue is with either how I've set up my model or how I'm querying the datastore (I have a suspicion that it may be to do with lazy loading or the default fetch group, but I'm not sure).
Before I explain what's happening it would help to understand the model.
Here is a simplified version of my model:
#PersistenceCapable
#Inheritance(customStrategy = "complete-table")
public class DataObject {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY, defaultFetchGroup="true")
protected Key theKey;
#Persistent()
protected String name;
//...
}
#PersistenceCapable
public class Class1 extends DataObject{
#Persistent()
#Element(dependent="true")
private List<Class2> listOfClass2 = new ArrayList<Class2>();
//...
}
#PersistenceCapable
public class Class2 extends DataObject{
#Persistent()
#Element(dependent="true")
private List<Class3> listOfClass2 = new ArrayList<Class3>();
//...
}
#PersistenceCapable
public class Class3 extends DataObject{
#Persistent()
private String value;
//...
}
And here is the code used to query the data store:
public class DataManager {
public DataObject get(
User user,
Class type,
Long id) throws OAuthRequestException
{
PersistenceManager mgr = getPersistenceManager();
DataObject obj = null;
try
{
obj = mgr.getObjectById(type, id);
getAllChildren(obj);
}
finally
{
mgr.close();
}
if(obj != null)
{
return obj;
}
else
{
throw new EntityNotFoundException("Entity not found");
}
}
/**
* Returns all of the children of the given object
* and their children etc. It is intended to 'touch' every object
* in the tree to accommodate for lazy loading.
*/
private List<StoredDataObject> getAllChildren(DataObject obj)
{
//...
}
}
The problem is that very occasionally, the query will be returned with all of the 'name' fields at a given level empty. For instance, If I retrieve an object of Class1, all of the child Class2 objects will have the 'name' attribute equal to "". The data is definitely in the data store because if I run the query again they will be populated correctly. I have never seen any of the other attributes empty, only the name field. Sometimes it occurs at the Class2 level, sometimes Class3, but never Class1 (as far as I have seen).
It is my understanding that any String attributes should automatically be included in the default fetch group, but am I possibly missing an annotation that forces the 'name' attribute to be retrieved every time?
New observation: When this occurs, it will happen consistently for about 15 minutes as long as I run the same query with the same user credentials. Could this be something to do with caching?

Salesforce (SFDC) - public, static, global keywords - use one list for entire class?

I'm having a hard understanding using public, static, and global keywords with my variables and methods.
Below is a snippet of my code. What I'm trying to do is upon page load, in my constructor create a Set of accountIDs that the user has access to (8-33 this is working). This set will be used to filter queries used in later methods.
What I'm finding is that public pageReference runSearch() has access to 'terrAccSet', but the public static List getsearchAccounts does not have access to it.
If I change it to public static Set terrAccSet, I don't get data in either of the system.debugs - what can I do?
global with sharing class MyClass {
public static List<FRM_Metrics_gne__c> accountSearchGmap {get; set;}
public Set<Id> terrAccSet;
public List<String> terrIdList;
//Constructor
public MyClass() {
terrAccSet = new Set<Id>();
terrIdList = new List<String>();
Set<Id> grpIdSet = new Set<Id>();
Id uid = '00570000001R95e'; //member of TWO territories
//UserTerritory Utid = [SELECT TerritoryId FROM UserTerritory where UserId = :userInfo.getUserId()];
List<UserTerritory> Utid = [SELECT TerritoryId FROM UserTerritory where UserId =: uid ];
for(UserTerritory usrTerr: Utid){
terrIdList.add(usrTerr.TerritoryId);
}
List<Group> grp = [Select Id from Group where RelatedID IN :terrIdList];
for (Group eachgroupd : grp ){
grpIdset.add(eachgroupd.Id);
}
List<AccountShare> accountidList = [SELECT AccountId,UserOrGroupId FROM AccountShare where UserOrGroupId in :grpIdset];
//all accounst that the user has access according to territory hiearchy
for(AccountShare eachas:accountidList ){
terrAccSet.add(eachas.AccountId);
}
}
public PageReference runSearch() {
//Has Data
system.debug('**terrAccSet runSearch** '+terrAccSet);
}
public static List<Custom_Object__c> getsearchAccounts(String multiSearchString) {
//terrAccSet variable is missing
system.debug('**terrAccSet getSearchAccounts** '+terrAccSet);
//logic
return accountSearchGmap;
}
}
Below is a snippet of my code. What I'm trying to do is upon page load, in my constructor create a Set of accountIDs that the user has access to (8-33 this is working). This set will be used to filter queries used in later methods.
This set should be an instance property, not static.
Use static when you want to create a method that does not affect the state of a controller or class, eg. a text parser-text in text out.
You should make the class Global if you want to create a package and make your class available outside your package so that other Apex code can invoke it, or if your class will create webService or REST methods to be exposed.
Public should be used to expose properties to the VisualForce pages that will consume the properties. Otherwise, use Private methods and properties for controller side only processing.
public static List getsearchAccounts(String multiSearchString) {
//terrAccSet variable is missing
system.debug('terrAccSet getSearchAccounts '+terrAccSet);
//logic
return accountSearchGmap;
}
This method should not be static because it accesses an instance property (it reads state).
Simple rule of thumb, if it is a visualforce page + controller, you shouldn't need anything static to do your normal work of querying the database and returning data to the page.

Create my own API

I use in my force.com application Apex Classes, and many of them have the same structure, I want to make an API to reuse it after.
For exaple, these are two classes :
//first class
public class insererActAct{
public List<Activites_actuelles__c> accts {get; set;}
public insererActAct(ApexPages.StandardController controller){
accts = new List<Activites_actuelles__c>();
accts.add(new Activites_actuelles__c());
}
public void addrow(){
accts.add(new Activites_actuelles__c());
}
public PageReference deleteRow(){
if (accts.size()>1)
{
accts.remove(accts.size()-1);
}
return null;
}
public PageReference save()
{
insert accts;
Assure__c theParent = new Assure__c(id=accts[0].Activites_actuelles__c);
PageReference acctPage = new ApexPages.StandardController(theParent).view();
acctPage.setRedirect(true);
return acctPage;
}
}
//second class
public class insererEnfants{
public List<Enfants__c> accts {get; set;}
public insererEnfants(ApexPages.StandardController controller){
accts = new List<Enfants__c>();
accts.add(new Enfants__c());
}
public void addrow(){
accts.add(new Enfants__c());
}
public PageReference deleteRow(){
if (accts.size()>1)
{
accts.remove(accts.size()-1);
}
return null;
}
public PageReference save()
{
insert accts;
Assure__c theParent = new Assure__c(id=accts[0].Parent__c);
PageReference acctPage = new ApexPages.StandardController(theParent).view();
acctPage.setRedirect(true);
return acctPage;
}
}
Can any one tell me it is possible or not, if yes, how can I do this, please ?
Do you mean you want to write code that works for different kinds of objects, rather than stating the type of object in the code?
It is possible to do this, by declaring your sObject variables with the sObject type, e.g, instead of
public List<Activites_actuelles__c> accts {get; set;}
you would put
public List<sObject> sObjects{get; set;}
and by referencing fields using get and put, e.g. instead of
Account theAccount = new Account();
theAccount.name = 'Fred';
you would put
sObject theSObject = new SObject();
theSObject.put('name', 'Fred');
I've not tried using code like this in a controller extension, but in theory since you can pass in any standard controller you ought to be OK.
You will need to think about how to create the parent object inside the save method, because you will need to pass in what type you want to create. It's quite complicated but it is possible to take in a string representing the object type (e.g. 'Account') and create a new object of that type:
Schema.getGlobalDescribe().get('Account').newSObject()
will get you a new Account. So you could replace 'Account' with any type passed in as a parameter.
For more information look up Dynamic Apex, Dynamic SOQL and Dynamic DML in the documentation.
A word of warning: Passing around object types and field names as strings means that the compiler will not know those types are mentioned in the code. So if you try and delete a custom object or rename a field, salesforce will not warn you that the object or field is in use and will allow you to do the deletion.
Another word of warning: Although this allows code reuse and that is a benefit, you may find it is not worth it. I avoid writing dynamic apex unless I absolutely have to. It is far more complex than ordinary apex and it is therefore difficult to debug and maitain, especially if someone other than yourself has to maintain it.

Resources