HTTP Method 'PATCH' not allowed. Allowed are POST,DELETE,GET,HEAD - salesforce

I have created a method to update the records in a case.
#RestResource(urlMapping= '/FieldCases/*')
global with sharing class RestCaseController {
#HttpPatch
global static String caseUpdate(String caseId, String caseStatus, String caseNote){
Case companyCase = [SELECT Id, Subject, Status, Description FROM Case WHERE Id = :caseId];
companyCase.Status = caseStatus;
companyCase.Description += caseNote;
update companyCase;
Return 'Updated';
}
}
and in work bench I am using
/services/apexrest/FieldCases
{"caseId" : "0037F00000bQYIjQAO",
"caseStatus" : "Working",
"caseNote" : "updating from the work bench"}
but I am getting the below error
HTTP Method 'PATCH' not allowed. Allowed are POST,DELETE,GET,HEAD

It worked alright for me. Here's a screenshot of the request in workbench:

Related

How to update values in a nested json file by Powershell

I want to update some values of below content which i believe a json file. This is the output of azure devops release definition and I need to reuse the content modifying some fields.
I can simply update values like id and name using these lines
$ReleaseDef.Name = $newReleaseName
$ReleaseDef.path = $folderQA
But I dont know how to update array fields like artifact and triggers. I can get values by calling $ReleaseDef.artifacts.sourceid
but can not set any values there , It throws errors like The property 'sourceid' cannot be found on this object. Verify that the
property exists and can be set.
Please suggest
source : userInterface
revision : 4
description :
createdBy : #{displayName=Jyotiprakash Nayak; url=https://azuredevopsdv
.ril.com/EntApps/_apis/Identities/2ca8bd5d-7797-4177-b7bb-2
6daa0d29ed9; _links=;
id=2ca8bd5d-7797-4177-b7bb-26daa0d29ed9;
uniqueName=domain\Jyotiprakash.Nayak; imageUrl=https://azuredev
opsdv.company.com/EntApps/_apis/GraphProfile/MemberAvatars/win.
Uy0xLTUtMjEtMjIwNzU5NTE2Ni03MjEyNTY2NjUtNTU2MTkwNDkyLTQ4NjY
yMw; descriptor=win.Uy0xLTUtMjEtMjIwNzU5NTE2Ni03MjEyNTY2NjU
tNTU2MTkwNDkyLTQ4NjYyMw}
createdOn : 2019-12-10T09:11:11.057Z
modifiedBy : #{displayName=Jyotiprakash Nayak; url=https://azuredevopsdv
.company.com/EntApps/_apis/Identities/2ca8bd5d-7797-4177-b7bb-2
6daa0d29ed9; _links=;
id=2ca8bd5d-7797-4177-b7bb-26daa0d29ed9;
uniqueName=Domain\Jyotiprakash.Nayak; imageUrl=https://azuredev
opsdv.comapny.com/EntApps/_apis/GraphProfile/MemberAvatars/win.
Uy0xLTUtMjEtMjIwNzU5NTE2Ni03MjEyNTY2NjUtNTU2MTkwNDkyLTQ4NjY
yMw; descriptor=win.Uy0xLTUtMjEtMjIwNzU5NTE2Ni03MjEyNTY2NjU
tNTU2MTkwNDkyLTQ4NjYyMw}
modifiedOn : 2019-12-13T09:16:13.463Z
isDeleted : False
variables :
variableGroups : {}
environments : {#{id=7; name=Stage 1; rank=1; owner=; variables=;
variableGroups=System.Object[]; preDeployApprovals=;
deployStep=; postDeployApprovals=;
deployPhases=System.Object[]; environmentOptions=;
demands=System.Object[]; conditions=System.Object[];
executionPolicy=; schedules=System.Object[];
currentRelease=; retentionPolicy=; processParameters=;
properties=; preDeploymentGates=; postDeploymentGates=;
environmentTriggers=System.Object[]; badgeUrl=https://azure
devopsdv.comapny.com/EntApps/_apis/public/Release/badge/e0b1a36
0-01a5-4eea-af57-b2a461559ac9/7/7}}
artifacts : {#{sourceId=e0b1a360-01a5-4eea-af57-b2a461559ac9:48;
type=Build; alias=_eCAM-Team-CI; definitionReference=;
isPrimary=True; isRetained=False}}
triggers : {#{artifactAlias=_eCAM-Team-CI;
triggerConditions=System.Object[];
triggerType=artifactSource}}
releaseNameFormat : Release-$(rev:r)
tags : {}
pipelineProcess : #{type=designer}
properties : #{DefinitionCreationSource=}
id : 7
name : Release-Template-1
path : \QA
projectReference :
url : https://azuredevopsdv.company.com/EntApps/e0b1a360-01a5-4eea-af
57-b2a461559ac9/_apis/Release/definitions/7
_links : #{self=; web=}
These attributes contain hash table values.
You should be able to update by specifying the key and its new value like so:
$ReleaseDef.artifacts["sourceid"] = "someValueHere"
Thanks all for your valuable helps, I finally made it work through some foreach loops.
```$artifact = $json.artifacts
foreach ($value in $artifact)
{
$value.alias = "_$newReleaseName"
$value.sourceId = "$($projectid):$($BuildID)"
}
foreach ($triggervalue in $snapshot.triggers)
{
$triggervalue.artifactAlias = "_$newReleaseName"
}```

Gmail API .NET: Get full message

How do I get the full message and not just the metadata using gmail api?
I have a service account and I am able to retrieve a message but only in the metadata, raw and minimal formats. How do I retrieve the full message in the full format? The following code works fine
var request = service.Users.Messages.Get(userId, messageId);
request.Format = UsersResource.MessagesResource.GetRequest.FormatEnum.Metadata;
Message message = request.Execute();
However, when I omit the format (hence I use the default format which is FULL) or I change the format to UsersResource.MessagesResource.GetRequest.FormatEnum.Full
I get the error: Metadata scope doesn't allow format FULL
I have included the following scopes:
https://www.googleapis.com/auth/gmail.readonly,
https://www.googleapis.com/auth/gmail.metadata,
https://www.googleapis.com/auth/gmail.modify,
https://mail.google.com/
How do I get the full message?
I had to remove the scope for the metadata to be able to get the full message format.
The user from the SO post have the same error.
Try this out first.
Go to https://security.google.com/settings/security/permissions
Choose the app you are working with.
Click Remove > OK
Next time, just request exactly which permissions you need.
Another thing, try to use gmailMessage.payload.parts[0].body.dataand to decode it into readable text, do the following from the SO post:
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.StringUtils;
System.out.println(StringUtils.newStringUtf8(Base64.decodeBase64(gmailMessage.payload.parts[0].body.data)));
You can also check this for further reference.
try something like this
public String getMessage(string user_id, string message_id)
{
Message temp =service.Users.Messages.Get(user_id,message_id).Execute();
var parts = temp.Payload.Parts;
string s = "";
foreach (var part in parts) {
byte[] data = FromBase64ForUrlString(part.Body.Data);
s += Encoding.UTF8.GetString(data);
}
return s
}
public static byte[] FromBase64ForUrlString(string base64ForUrlInput)
{
int padChars = (base64ForUrlInput.Length % 4) == 0 ? 0 : (4 - (base64ForUrlInput.Length % 4));
StringBuilder result = new StringBuilder(base64ForUrlInput, base64ForUrlInput.Length + padChars);
result.Append(String.Empty.PadRight(padChars, '='));
result.Replace('-', '+');
result.Replace('_', '/');
return Convert.FromBase64String(result.ToString());
}

Camel Rest DSL - AggregationStrategy strange behavior

The title is a little a canvasser, and it is of course my fault if it does not work, as it should.
I want to perform a data transfer from a rdbms to solr and mongo db.
To do that, I have to complete the following steps (for example) :
Get customers ids to transfer
Get custometrs details
Get customers invoices
Get customers payments
Then, aggregate and save to mongo db and solr for indexing.
Here is my code, but I can not get it to work :
from("seda:initial-data-transfer")
.setProperty("recipientList", simple("direct:details,direct:invoices,direct:payments"))
.setProperty("afterAggregate", simple("direct:mongodb,direct:solr"))
.setBody(constant("{{query.initial-data-transfer.ids}}"))
.to(jdbc)
.process(new RowSetIdsProcessor())
.split().tokenize(",", 1000) // ~200k ids - group by 1000 ids
.to("direct:customers-ids");
from("direct:customers-ids")
.recipientList(exchangeProperty("recipientList").tokenize(","))
// ? .aggregationStrategy(new CustomerAggregationStrategy()).parallelProcessing()
.aggregate(header("CamelCorrelationId"), new CustomerAggregationStrategy())
.completionPredicate(new CustomerAggregationPredicate()) // true if details + invoices + payments, etc ....
// maybe a timeOut here ?
.process(businessDataServiceProcessor)
.recipientList(exchangeProperty("afterAggregate").tokenize(","));
from("direct:details")
.setHeader("query", constant("{{query.details}}"))
.bean(SqlTransform.class,"detailsQuery").to(jdbc)
.process(new DetailsProcessor());
from("direct:invoices")
.setHeader("query", constant("{{query.invoices}}"))
.bean(SqlTransform.class,"invoicessQuery").to(jdbc)
.process(new InvoicesProcessor());
I do not understand how works AggregationStrategy.
Sometimes, I can perform 2 or 3 blocks of 1000 ids, and save to mongo DB and Solr but after, all exchanges are empty in the aggregationStrategy ...
I tried a lot of thinks .. but each time, the aggregation fail.
Thanks for your help
Update :
Here is a part of the CustomerAggregationStrategy :
public class CustomerAggregationStrategy implements AggregationStrategy {
#Override
public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
Message newIn = newExchange.getIn();
CustomerDataCollector collector = null;
if (oldExchange == null) {
int completionSize = newExchange.getProperty("completionSize", Integer.class);
collector = new CustomerDataCollector(completionSize);
CollectData(collector, newIn, newExchange);
newIn.setBody(collector);
return newExchange;
}
collector = oldExchange.getIn().getBody(CustomerDataCollector.class);
CollectData(collector, newIn, newExchange);
return oldExchange;
}
private void CollectData(CustomerDataCollector collector, Message message, Exchange exchange) {
String recipientListEndpoint = (String)exchange.getProperty(Exchange.RECIPIENT_LIST_ENDPOINT);
switch (recipientListEndpoint){
case "direct://details" :
collector.setDetails(message.getBody(Map.class));
break;
case "direct://invoices" :
collector.setInvoices(message.getBody(Map.class));
break;
case "direct://payments" :
collector.setPayments(message.getBody(Map.class));
break;
}
}
}
Update :
I can log this in the CustomerAggregationStrategy :
String camelCorrelationId = (String)exchange.getProperty(Exchange.CORRELATION_ID);
[t-AggregateTask] .i.c.a.CustomerAggregationStrategy : CustomerAggregationStrategy.CollectData : direct://details ID-UC-0172-50578-1484523575668-0-5
[t-AggregateTask] .i.c.a.CustomerAggregationStrategy : CustomerAggregationStrategy.CollectData : direct://invoices ID-UC-0172-50578-1484523575668-0-5
[t-AggregateTask] .i.c.a.CustomerAggregationStrategy : CustomerAggregationStrategy.CollectData : direct://payments ID-UC-0172-50578-1484523575668-0-5
Same values for the CamelCorrelationId as expected.
I thing the CamelCorrelationId is correct. Doesn't it ?
Ok, it is better now.
After the tokeniszer, I set the property CustomCorrelationId like this.
.split().tokenize(",", 1000)
.setProperty("CustomCorrelationId",header("breadcrumbId"))
.to("direct:customers-ids")
And aggregate on this value like this :
from("direct:customers-ids")
.recipientList(exchangeProperty("recipientList").tokenize(","))
from("direct:details")
.setHeader("query", constant("{{query.details}}"))
.bean(SqlTransform.class,"detailsQuery").to(jdbc)
.process(new DetailsProcessor())
.to("direct:aggregate");
...
from("direct:aggregate").routeId("aggregate")
.log("route : ${routeId}")
.aggregate(property("CustomCorrelationId"), new CustomAggregationStrategy())
.completionPredicate(new CustomerAggregationPredicate())
.process(businessDataServiceProcessor)
.recipientList(exchangeProperty("afterAggregate").tokenize(","));
This work fine now and data are correctly aggregated. Thanks for your help.
You pointed out the way.

Pagination in Google cloud endpoints + Datastore + Objectify

I want to return a List of "Posts" from an endpoint with optional pagination.
I need 100 results per query.
The Code i have written is as follows, it doesn't seem to work.
I am referring to an example at Objectify Wiki
Another option i know of is using query.offset(100);
But i read somewhere that this just loads the entire table and then ignores the first 100 entries which is not optimal.
I guess this must be a common use case and an optimal solution will be available.
public CollectionResponse<Post> getPosts(#Nullable #Named("cursor") String cursor,User auth) throws OAuthRequestException {
if (auth!=null){
Query<Post> query = ofy().load().type(Post.class).filter("isReviewed", true).order("-timeStamp").limit(100);
if (cursor!=null){
query.startAt(Cursor.fromWebSafeString(cursor));
log.info("Cursor received :" + Cursor.fromWebSafeString(cursor));
} else {
log.info("Cursor received : null");
}
QueryResultIterator<Post> iterator = query.iterator();
for (int i = 1 ; i <=100 ; i++){
if (iterator.hasNext()) iterator.next();
else break;
}
log.info("Cursor generated :" + iterator.getCursor());
return CollectionResponse.<Post>builder().setItems(query.list()).setNextPageToken(iterator.getCursor().toWebSafeString()).build();
} else throw new OAuthRequestException("Login please.");
}
This is a code using Offsets which seems to work fine.
#ApiMethod(
name = "getPosts",
httpMethod = ApiMethod.HttpMethod.GET
)
public CollectionResponse<Post> getPosts(#Nullable #Named("offset") Integer offset,User auth) throws OAuthRequestException {
if (auth!=null){
if (offset==null) offset = 0;
Query<Post> query = ofy().load().type(Post.class).filter("isReviewed", true).order("-timeStamp").offset(offset).limit(LIMIT);
log.info("Offset received :" + offset);
log.info("Offset generated :" + (LIMIT+offset));
return CollectionResponse.<Post>builder().setItems(query.list()).setNextPageToken(String.valueOf(LIMIT + offset)).build();
} else throw new OAuthRequestException("Login please.");
}
Be sure to assign the query:
query = query.startAt(cursor);
Objectify's API uses a functional style. startAt() does not mutate the object.
Try the following:
Remove your for loop -- not sure why it is there. But just iterate through your list and build out the list of items that you want to send back. You should stick to the iterator and not force it for 100 items in a loop.
Next, once you have iterated through it, use the iterator.getStartCursor() as the value of the cursor.

Could not get HTTP Header Attribute in Google App Engine

In my GAE, I have the following segment of code:
accountId := r.Header.Get("user_id")
if accountId == "" {
accountId = r.FormValue("user_id")
if accountId == "" {
utility.CreateErrorResponse(w, "User ID is missing from request")
return
}
}
the code basically try to read "user_id" from Header but the accountId is empty making the program to return early unexpected.
Here is my C# client code:
...
HttpWebRequest req = (HttpWebRequest) WebRequest.Create(data);
req.Method = "GET";
req.KeepAlive = false;
foreach (ExtraAttribute att in mAttributes)
{
req.Headers.Add( att.mKey, att.mValue);
}
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
...
where the foreach help me add the "user_id" attribute to the Request Header.
(And I have confirmed the existence of "user_id" entry in Fiddler)
What is the next thing I should do to find out whats going on?
Thanks
I just found that after i changed the attribute name from "user_id" to "UserId" and everything works now...
Don't know if its the capital case or the underscore problem.

Resources