It is necessary to perform the planned action through the apex scheduler - salesforce

i have this code:
public static String currencyConverter() {
allCurrency test = new allCurrency();
HttpRequest request = new HttpRequest();
HttpResponse response = new HttpResponse();
Http http = new Http();
request.setEndpoint(endPoint);
request.setMethod('GET');
response = http.send(request);
String JSONresponse = response.getBody();
currencyJSON currencyJSON = (currencyJSON)JSON.deserialize(JSONresponse, currencyJSON.class);
test.USD = currencyJSON.rates.USD;
test.CAD = currencyJSON.rates.CAD;
test.EUR = currencyJSON.rates.EUR;
test.GBP = currencyJSON.rates.GBP;
Log__c logObject = new Log__c();
logObject.Status_Code__c = String.valueOf(response.getStatusCode());
logObject.Response_Body__c = response.getBody();
insert logObject;
if (response.getStatusCode() == 200) {
Exchange_Rate__c ExchangeRateObject = new Exchange_Rate__c();
ExchangeRateObject.CAD__c = currencyJSON.rates.CAD;
ExchangeRateObject.EUR__c = currencyJSON.rates.EUR;
ExchangeRateObject.GBP__c = currencyJSON.rates.GBP;
ExchangeRateObject.USD__c = currencyJSON.rates.USD;
ExchangeRateObject.Log__c = logObject.id;
insert ExchangeRateObject;
}
return JSON.serialize(test);
}
Here I am getting different currencies and then calling them in LWC and also I create two objects with values.
I want these objects to be created every day at 12PM.
Tell me how to implement this through the apex scheduler.

You need a class that implements Schedulable. Can be this class, just add that to the header and add execute method. Or can be separate class, doesn't matter much.
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_scheduler.htm
Something like
public with sharing MyClass implements Schedulable{
public static String currencyConverter() { ... your method here }
public void execute(SchedulableContext sc) {
currencyConverter();
}
}
Once your class saves OK you should be able to schedule it from UI (Setup -> Apex Classes -> button) or with System.schedule 1-liner from Developer Console for example.
Alternative would be to have a scheduled Flow - but that's bit more work with making your Apex callable from Flow.
P.S. Don't name your variables test. Eventually some time later you may need "real" stuff like Test.isRunningTest() and that will be "fun". It's like writing
Integer Account = 5; // happy debugging suckers

Related

Using Dapper in C# MVVM and SQL Server 2019/Visual Studios Pro 2019

I am writing an application using C#, WPF, MVVM and SQL Server, and I am using Dapper as an ORM. Below is a snippet of the sample code I am trying to make work:
public List<MAKE THIS GENERIC> ExecuteSQLSPROC(string SPROCName, SqlParameter[] parameters, IEnumerable<MAKE THIS GENERIC> model)
{
using (IDbConnection connection = new System.Data.SqlClient.SqlConnection(DBHelper.CNNVal("MyDatabaseName")))
{
System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand();
command.Connection = (SqlConnection)connection;
command.CommandText = SPROCName;
DynamicParameters parms = new DynamicParameters();
for (int i = 0; i < parameters.Length; i++)
{
var parmname = parameters[i].ParameterName;
var parmvalue = parameters[i].Value;
// I KNOW I can put DIRECTION as a parameter variable but right now I don't want to!!
parms.Add(parmname, parmvalue);
}
var output = connection.Query<Make THIS GENERIC>(SPROCName, parms, commandType: CommandType.StoredProcedure).ToList();
return output; // return the recordset to the caller - a List<> of one object/model is acceptable - NOT POPULATING EXCEL spreadsheet with
// the results
}
}
I want to call this piece of code (which does not compile right now for obvious reasons) by supplying any ViewModel and be able to execute this code as if the ViewModel is generic within the routine. I need to know how to correctly code the above and also make the call to this routine with generic ViewModels (probably using a Lambda expression of some sort).
Basically, I want to be able to say "execute this SPROC, with these dynamic parameters and map the output to a ViewModel that is generic and return the results to the caller. Next time you're called it will be same logic, different SPROC, different parameters and ViewModel". I do NOT want extraneous comments that DO NOT directly answer this question. I know that I can add the parameter direction in a call the SQL SPROCs; but that knowledge is irrelevant to this question I am asking!
You can put your method in a generic class if you have other methods:
public class DbStuff<T>
{
public IList<T> ExecuteSQLSPROC(string SPROCName, SqlParameter[] parameters, IEnumerable<T> model)
{
using (IDbConnection connection = new System.Data.SqlClient.SqlConnection(DBHelper.CNNVal("MyDatabaseName")))
{
System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand();
command.Connection = (SqlConnection)connection;
command.CommandText = SPROCName;
DynamicParameters parms = new DynamicParameters();
for (int i = 0; i < parameters.Length; i++)
{
var parmname = parameters[i].ParameterName;
var parmvalue = parameters[i].Value;
// I KNOW I can put DIRECTION as a parameter variable but right now I don't want to!!
parms.Add(parmname, parmvalue);
}
var output = connection.Query<T>(SPROCName, parms, commandType: CommandType.StoredProcedure).ToList();
return output; // return the recordset to the caller - a List<> of one object/model is acceptable - NOT POPULATING EXCEL spreadsheet with
// the results
}
}
}
Then call it via:
var stuff = new DbStuff<MyViewModel>();
var results = stuff.ExecuteSQLSPROC("", blah, blah);
Or just make the method generic:
public IList<T> ExecuteSQLSPROC<T>(string SPROCName, SqlParameter[] parameters, IEnumerable<T> model)

Get velocity template from database in Springboot

I have to get velocity templates from database in Spring boot and Spring data project.I have not tried any code yet as I am new to all technologies(Velocity, Spring boot and data) and not finding anything on google. Does anybody tried here to get template from db, please suggest me some links or anything else which i can refer?
Update: I have binding classes in db (in grails) and I have to access process method from java .In db class is ,
class bindingSubject {
def log
def process = { pub,listForMail ->
def mapBinding = [:]
def fund
def perimeters = pub.sub.entities
perimeters.each(){ entity ->
if (fu == null){
if (entity instanceof S)
fu = entity.fu
if (entity instanceof Fund)
fu = fu
}
}mapBinding.entity = fu.name return mapBinding
}
}
and java code written to
-> Load script
mapScriptClass = new HashMap<String, Object>();
if (script != null) {
if (mapScriptClass.get(name) == null) {
GroovyCodeSource groovySource = new GroovyCodeSource(script,name,"");
GroovyClassLoader classLoader = new GroovyClassLoader(this.getClass().getClassLoader());
// Load string as Groovy script class.
Class scriptClass = classLoader.parseClass(groovySource);
try {
Object classInstance = scriptClass.newInstance();
ApplicationContext ctx = (ApplicationContext)ServletContextHolder
.getServletContext().getAttribute(ApplicationAttributes.APPLICATION_CONTEXT);
ctx.getAutowireCapableBeanFactory().autowireBeanProperties(classInstance, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false);
mapScriptClass.put(name, classInstance);
return classInstance;
To call process method from db(in grails this works , how to do it in java?)
Object scriptClass = loadScriptService.getScriptClass("scriptBindingSubject"+templateMail.getId(),
templateMail.getScriptBindingSubject());
if (scriptClass != null) {
try{
bindingSubject = scriptClass.process(pub,subMail);
}
now i am not sure how to call process method from java(to db) to bind properties
Thanks.
As you write, the templates are stored in the database.
So you need to read them (using JDBC or JPA) and depending on how they are stored, you will get a String, char[] or byte[].
You can convert all of them into a java.io.Reader like
CharArrayReader, StringReader,
how this can be done for a byte[] you can see in this tutorial
SimpleTemplateEngine has a method
createTemplate(Reader reader)
that finally creates the template for the reader.
Hope that helps.

How do I write a test class for Messaging.SingleEmailMessage apex class?

I have written the below Apex class that processes incoming email that are sent to an email service address and creates a new task from the incoming mail and then associates this new task with a matching record in salesforce. The match is done on the record name and incoming email subject. The class also sends an email notifying the "Assigned to" user that they have received a reply on a request they are working on.
This works perfect in Sandbox but I have no experience writing test classes. Can anyone advise how I write the test class for the below?
global class RequestEmailHandler implements Messaging.InboundEmailHandler {
global Messaging.InboundEmailResult handleInboundEmail(Messaging.InboundEmail email, Messaging.InboundEnvelope envelope) {
Messaging.InboundEmailResult result = new Messaging.InboundEmailresult();
String myPlainText = email.plainTextBody;
String subject = email.fromName + ' - ' + email.subject;
system.debug(email);
subject = subject.left(255);
Request__c request;
if (subject != null && subject.trim().length() > 0 && subject.indexOf('(R-') > 0) {
Integer idx = subject.indexOf('(R-');
String requestName = subject.substring(idx+1, subject.indexOf(')', idx));
request = [SELECT Id, Assigned_To__c FROM Request__c WHERE Name = :requestName];
}
if (request == null) {
result.message = 'We were unable to locate the associated request.This may be due to the unique "R" number being removed from the subject line.\n Please include the original email subject when replying to any emails.';
result.success = false;
return result;
}
// Add the email plain text into the local variable
Task task = new Task(
WhatId = request.Id,
Description = myPlainText,
Priority = 'Normal',
Status = 'Completed',
Type = 'Email',
Subject = subject,
ActivityDate = System.today(),
RecordTypeId = '01250000000HkEw');
insert task;
//Find the template
EmailTemplate theTemplate = [select id, name from EmailTemplate where DeveloperName = 'New_Email_Reply2'];
//Create a new email right after the task
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
//Add email To addresses to list
List<String> toAddresses = new List<String>();
toAddresses.add(email.fromAddress);
//Set the list of to addresses
mail.setToAddresses(toAddresses);
//Set the template id
mail.setTemplateId(theTemplate.id);
//The Id of the user
mail.setTargetObjectId(request.Assigned_To__c);
//Set the id of the request
mail.setWhatId(request.Id);
//If you need the email also saved as an activity, otherwise set to false
mail.setSaveAsActivity(false);
//Send Email
try {
Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});
}
catch (EmailException e) {
system.debug('sendEmail error: ' + e.getMessage());
}
// Save attachments, if any
if (email.textAttachments != null)
{
for(Messaging.Inboundemail.TextAttachment tAttachment : email.textAttachments)
{
Attachment attachment = new Attachment();
attachment.Name = tAttachment.fileName;
attachment.Body = Blob.valueOf(tAttachment.body);
attachment.ParentId = request.Id;
insert attachment;
}
}
//Save any Binary Attachment
if (email.binaryAttachments != null)
{
for(Messaging.Inboundemail.BinaryAttachment bAttachment : email.binaryAttachments) {
Attachment attachment = new Attachment();
attachment.Name = bAttachment.fileName;
attachment.Body = bAttachment.body;
attachment.ParentId = request.Id;
insert attachment;
return result;
}
}
return result;
}
}
Below is my attempt which is only getting 24% coverage. I know it is missing vital code but I do not know enough about test classes to take it any further.
Can anyone assist?
Test Class
#isTest
public class testforemail {
static testMethod void insertRequest() {
Request__c requestToCreate = new Request__c();
requestToCreate.Subject__c= 'test';
requestToCreate.Requested_By_Email__c= 'graham.milne#fmr.com';
insert requestToCreate;
Messaging.InboundEmail email = new Messaging.InboundEmail();
Messaging.InboundEnvelope envelope = new Messaging.InboundEnvelope();
Request__c testRequest = [select Id,Name from Request__c limit 1];
System.debug(testRequest.Name);
email.subject = (testRequest.Name);
email.fromName = 'test test';
email.plainTextBody = 'Hello, this a test email body. for testing purposes only.Phone:123456 Bye';
Messaging.InboundEmail.BinaryAttachment[] binaryAttachments = new Messaging.InboundEmail.BinaryAttachment[1];
Messaging.InboundEmail.BinaryAttachment binaryAttachment = new Messaging.InboundEmail.BinaryAttachment();
binaryAttachment.Filename = 'test.txt';
String algorithmName = 'HMacSHA1';
Blob b = Crypto.generateMac(algorithmName, Blob.valueOf('test'),
Blob.valueOf('test_key'));
binaryAttachment.Body = b;
binaryAttachments[0] = binaryAttachment ;
email.binaryAttachments = binaryAttachments ;
envelope.fromAddress = 'user#fmr.com';
// Add the email plain text into the local variable
Task task = new Task(
WhatId = (testRequest.Id),
Description = email.plainTextBody,
Priority = 'Normal',
Status = 'Completed',
Type = 'Email',
Subject = (testRequest.Name),
ActivityDate = System.today(),
RecordTypeId = '01250000000HkEw');
insert task;
// setup controller object
RequestEmailHandler catcher = new RequestEmailHandler();
Messaging.InboundEmailResult result = catcher.handleInboundEmail(email, envelope);
System.assertEquals( true,result.success );
}
}
The first step is to identify what lines of code are not being covered by your test class.
If you're using Eclipse, you can see this from the Apex Test Runner View.
Or, you can see this from the Developer console as well.
Another thing you need to consider is the isolation of your DML operations in a separate utility class.
public class TestUtils
{
// create request objects method here
// create task objects method here
}
Also, check your debug logs and make sure your code is not throwing any exceptions (i.e., null pointer exceptions, DML exceptions, etc.)
You must also add assertions to check that your code is behaving as expected.
Hope this helps.
The main thing you need to do is to test as many use cases as you can via unit tests.
So, setup data for specific case and run you email processing. After email, check the result using System.assertEquals(). Make separate tests for each use case.
Then, if you don't hit at least 75%, check what is not covered. You, probably, either don't need that code (in case you covered all use cases), or don't write a test for use case, which uses those lines of code.

AppEngine + Datastore + Objectify: Http Request returns inconsistent responses

I am implementing AppEngine server as a backend for my Android application. I use Datastore, I query it via Objectify service and I use Endpoints that I call via URL.
I have an entity User with properties like this:
#Id
Long id;
/**
* Name or nickname of the user
*/
public String name;
#Index
public String email;
#JsonIgnore
List<Key<User>> friends;
public User()
{
devices = new ArrayList<String>();
friendsWithKey = new ArrayList<Key<User>>();
}
public static User findRecordById(Long id)
{
return ofy().load().type(User.class).id(id).now();
}
#ApiMethod(name = "friends", httpMethod = "GET", path = "users/{userId}/friends")
public JSONObject getFriends(#Named("userId") String userId)
{
User user = User.findRecordById(Long.parseLong(userId));
JSONObject friendsObject = new JSONObject();
JSONArray jsonArray = new JSONArray();
JSONObject friend;
List<User> userList = new ArrayList<User>();
if (user.friendsWithKey != null)
{
for (Key<User> id : user.friendsWithKey)
{
friend = new JSONObject();
User user1 = User.findRecordById(id.getId());
userList.add(user1);
friend.put("name", user1.name);
friend.put("email", user1.email);
friend.put("id", user1.id);user1.lastTimeOnline.getTime());
jsonArray.add(friend);
}
friendsObject.put("friends", jsonArray);
}
return friendsObject;
}
It sometimes returns only a subset of friends. It is weird and I do not get where I could go wrong. If I get the User object from the DB, it already has a wrong List of Key values. But if I look into the database via console, I can see all of the users that ahve been added as friends.
I reaally need to fix this bug. Please, help.
It is very strange because it only happens once in a while and is non-deterministic in every way.

Salesforce error while makin a call to a web service api

I get the following error when I call the function add()
You have uncommitted work pending. Please commit or rollback before calling out
I call the getItems() to populate the drop down and then the add function to insert the selected item from the drop down
public PageReference add() {
insert technology;
return null;
}
public List<SelectOption> getItems() {
List<SelectOption> options = new List<SelectOption>();
List<Technology__c> AddedT=[SELECT Name FROM Technology__c];
HttpRequest req = new HttpRequest();
req.setMethod('GET');
req.setEndpoint('http://submit.toolsberry.com/sfdc/technologies');
Http http = new Http();
HTTPResponse res = http.send(req);
String response=res.getBody();
XmlStreamReader reader = new XmlStreamReader(response);
List<String> AllTech = new List<String>();
while(reader.hasNext()) {
if (reader.getEventType() == XmlTag.START_ELEMENT) {
if ('string' == reader.getLocalName()) {
while(reader.hasNext()) {
if (reader.getEventType() == XmlTag.END_ELEMENT) {
break;
} else if (reader.getEventType() == XmlTag.CHARACTERS) {
String tname = reader.getText();
AllTech.add(tname);
}
reader.next();
}
}
}
reader.next();
}
}
This is because you need to do all your DML AFTER you are done with any callouts, not before. So any insert/update/upsert or delete statements must follow any http.send(req); calls.
** Looks like your list is getting repopulated after you call the add() method, because your list resides in a getter method **
This is thread-specific and must occur in the sequence per any given thread. So, for example, when a user clicks a button with an action method, all DML statements in that call must follow any callouts that happen in the same thread. Same for a trigger or batch Apex.
Having a getter/setter somewhere that is updating data somehow can cause this. Eg:
public String someProperty
{
get
{
return [SELECT Name FROM CustomObject__c WHERE Id = :this.someId];
}
set(String s)
{
CustomObject__c c = [SELECT Name FROM CustomObject__C WHERE Id = :this.someId]
c.Name = s;
update c;
}
}
Also, never put a callout in a getter. Always put a callout in an explicit method that does it once and only once. Getters will get fired multiple times and callouts have strict limitations in Apex.

Resources