Array - RESTFUL - rest

Is there a way for me to send an array in Restful Web Services?
I am currently using : #Produces(MediaType.TEXT_PLAIN)
When I tried to use below code, I always get Null Pointer Exception for the methodClass value.
public int adaptiveAuth( #FormDataParam("uuid") String uuID,
#FormDataParam("browserinfo") String browserInfo,
#FormDataParam("ipint") long ipInt,
#FormDataParam("lat") double latiTude,
#FormDataParam("longitude") double longiTude,
#FormDataParam("sessionid") String sessionID,
#FormDataParam("spid") String spID,
#FormDataParam("tr") int tR,
#FormDataParam("jsnum") int jsNum,
#FormDataParam("fingerprint") String fingerPrint ,
#FormDataParam("methodset") MethodClass[][] methodSet) throws SQLException{
Is there any other way for me to send/receive MethodClass[][] in Restful Web Service?
Sample data for MedthodClass[1][1]
Thank you.

Related

Constructor not defined error after setting date fields as null during object creation

I have created a wrapper class to create an Object and send it as a request to a third party system. It was working well. But after I added a two new arguments of the Datatype Date, I am getting the below error.
Constructor not defined: [SFDC_DataObject.CustomerAccountObject].<Constructor>(Id, String, Id, String, Id, String, Integer, NULL, String, String, Id, String, NULL, String, String, String, String)
The request that I am creating and sending is as below.
SFDC_DataObject.CustomerAccountObject cusAccObj = new SFDC_DataObject.CustomerAccountObject(o.AccountId, o.Customer_Name__c, o.Agency_Name__r.Id,o.Agency_Name_OB__c, o.Opportunity.OwnerId, o.Opportunity.Owner.FederationIdentifier, PrimarySalesSplitPercent, null, secSOSalesforceId.get(o.OpportunityId), secSOSalesforceEmail.get(o.OpportunityId), o.Opportunity.Customer_Success_Manage__r.Id, o.Opportunity.Customer_Success_Manage__r.FederationIdentifier, null, o.Billing_Email__c, o.Billing_Phone__c, o.Bill_To_Name__c, o.Billing_Notes__c);
My wrapper class for the same object is as below.
public class CustomerAccountObject {
public String sfCustomerId;
public String customerName;
public String sfAgencyId;
public String agencyName;
public String sfPrimarySalesOwnerId;
public String primarySalesOwnerEmail;
public Integer primarySalesOwnerPercentage;
public Date primarySalesOwnerEffectiveFrom;
public String sfSecondarySalesOwnerId;
public String secondarySalesOwnerEmail;
public Date secondarySalesOwnerEffectiveFrom;
public String sfAccountManagerId;
public String accountManagerEmail;
public String billingEmail;
public String billingPhone;
public String billingName;
public String billingNotes;
public CustomerAccountObject() {}
public CustomerAccountObject(String sfCustomerId, String customerName, String sfAgencyId, String agencyName, String sfPrimarySalesOwnerId, String primarySalesOwnerEmail, Integer primarySalesOwnerPercentage, Date primarySalesOwnerEffectiveFrom, String sfSecondarySalesOwnerId, String secondarySalesOwnerEmail, Date secondarySalesOwnerEffectiveFrom, String sfAccountManagerId, String accountManagerEmail, String billingEmail, String billingPhone, String billingName, String billingNotes) {
this.sfCustomerId = sfCustomerId;
this.customerName = customerName;
this.sfAgencyId = sfAgencyId;
this.agencyName = agencyName;
this.sfPrimarySalesOwnerId = sfPrimarySalesOwnerId;
this.primarySalesOwnerEmail = primarySalesOwnerEmail;
this.primarySalesOwnerPercentage = primarySalesOwnerPercentage;
this.primarySalesOwnerEffectiveFrom = primarySalesOwnerEffectiveFrom;
this.sfSecondarySalesOwnerId = sfSecondarySalesOwnerId;
this.secondarySalesOwnerEmail = secondarySalesOwnerEmail;
this.secondarySalesOwnerEffectiveFrom = secondarySalesOwnerEffectiveFrom;
this.sfAccountManagerId = sfAccountManagerId;
this.accountManagerEmail = accountManagerEmail;
this.billingEmail = billingEmail;
this.billingPhone = billingPhone;
this.billingName = billingName;
this.billingNotes = billingNotes;
}
}
I began getting the error after I added the null for the Date arguments I.e primarySalesOwnerEffectiveFrom and secondarySalesOwnerEffectiveFrom during the Object creation.
Can anyone please let me know what am I doing wrong here.
The order is wrong.
In c-tor definition you have
String sfCustomerId, String customerName, String sfAgencyId, String
agencyName, String sfPrimarySalesOwnerId, String
primarySalesOwnerEmail, Integer primarySalesOwnerPercentage, Date
primarySalesOwnerEffectiveFrom, String sfSecondarySalesOwnerId, String
secondarySalesOwnerEmail, Date secondarySalesOwnerEffectiveFrom + 6 more Strings
So
... Integer, Date, String, String, Date, ...
But the code that calls it goes
o.AccountId, o.Customer_Name__c,
o.Agency_Name__r.Id,o.Agency_Name_OB__c, o.Opportunity.OwnerId,
o.Opportunity.Owner.FederationIdentifier, PrimarySalesSplitPercent,
null, secSOSalesforceId.get(o.OpportunityId),
secSOSalesforceEmail.get(o.OpportunityId),
o.Opportunity.Customer_Success_Manage__r.Id,
o.Opportunity.Customer_Success_Manage__r.FederationIdentifier, null, +
4 strings
There are extra 2 strings before 2nd null. And only 4 strings after it. You need to inject that null just after secSOSalesforceEmail?
This will get only worse to maintain as time goes on. Consider making a simple constructor and making the properties public. You could then set them after constructor in normal call. And if you don't need dates you just don't write line that sets date fields instead of injecting null at right position.
Follow-up edit
Not sure if there's an official guide to that technique or a blog post. Tools like Apex-PMD complain when you make methods with too many arguments, rules like "Avoid long parameter lists".
One way would be to do something like this:
SFDC_DataObject.CustomerAccountObject cusAccObj = new SFDC_DataObject.CustomerAccountObject();
cusAccObj.sfCustomerId = o.AccountId;
cusAccObj.customerName = o.Customer_Name__c;
cusAccObj.sfAgencyId = o.Agency_Name__c;
cusAccObj.agencyName = o.Agency_Name_OB__c;
cusAccObj.sfPrimarySalesOwnerId = o.Opportunity.OwnerId;
cusAccObj.primarySalesOwnerEmail = o.Opportunity.Owner?.FederationIdentifier;
cusAccObj.primarySalesOwnerPercentage = PrimarySalesSplitPercent;
// cusAccObj.primarySalesOwnerEffectiveFrom = null; // just don't bother with the line?
cusAccObj.sfSecondarySalesOwnerId = secSOSalesforceId.get(o.OpportunityId);
// ..
That's not very object oriented, not very elegant but caller has full control on the mapping. Problem will be if you need to map new field and this has been copy-pasted into 10 places. You'll have to update them all (which will be easier than adding N-th parameter to long call but still)
Another way would be to create a baseline constructor that takes whole Order object (it's an Order, right?), it'd map the fields internally. Then if needed - you specify some extra fields after constructor. Or maybe make few constructors?
public CustomerAccountObject(){
// I'm parameterless, I'm doing nothing! I'm just here if somebody needs a really custom field mapping or JSON deserialisations need a parameterless one
}
public CustomerAccountObject(Order o){
// I can map all fields from Order! Want to map new field? Just chuck it in here!
sfCustomerId = o.AccountId;
// ...
}
public CustomerAccountObject(Order o, Map<Id, String> secSOSalesforceId, Map<Id, String> secSOSalesforceEmail){
// I can do everything above and few more fields too!
this(o);
sfSecondarySalesOwnerId = secSOSalesforceId.get(o.OpportunityId);
secondarySalesOwnerEmail = secSOSalesforceEmail.get(o.OpportunityId);
}
You have bit of code reuse, the Order fields mapping is defined in just 1 place, just 1 line to change in future. You don't have an orgy of this everywhere anymore. And then your call if you really need the last constructor or you'll call the one that just takes Order o and then set the 2 extra fields after it finishes.

Handling of Incorrect Value for type Integer as RequestParam in REST API in Spring Boot Application

I have a problem with one of the negative scenarios of Testing an API.
I have a spring boot application with one RestController which takes in a RequestParam("id") and i return back the same id along with HttpStatus.OK.
When i hit GET API like : http://localhost:8080/Temp/getInteger?id=%23abcd
the value that gets assigned to id is 43981 which i don't understand how it got assigned.
Ideally i don't expect this String to be converted into an Integer, Can someone help me with this?
Code:
#RestController
#RequestMapping("/Temp")
public class TempController{
#RequestMapping(method=RequestMethod.GET, path= "/getInteger")
public ResponseEntity<Object> getInteger(#RequestParam("id") Integer id){
return new ResponseEntity(id,HttpStatus.OK);
}
}
Request:
http://localhost:8080/Temp/getInteger?id=%23abcd
Output :
Http Status : 200 OK
Response Body : 43981
From UTF-8 URL Encoded Characters: %23 is # and
from hexadecimal number system:
abcd is 43981
So it can be cast to INT. You can add a letter "e" and get a new number 703710. If you want to avoid it you need to add validation.

Passing parameters to GET in REST

I am trying to pass parameters with a GET request to a REST web service:
My class has the path defined as follows:
#Path("/ws")
public class RegistrationWS {
The method that I am calling has the path defined as:
#GET
#Produces("text/plain")
#Path("/{key}/{deviceId}")
public String getText(#QueryParam("key") String key, #QueryParam("deviceId") String deviceId) {
When I run the client, I get back the word 'failure', which is what my getText() method returns if the key was null:
// Get plain text
String registrationResponse = service.path("rest").path("ws/"+DEF+"/"+"ABC")
.accept(MediaType.TEXT_PLAIN)
.get(String.class);
Am I building the URL correctly in the client?

RESTEasy mapping a "legacy" Moodle REST service

I'm trying to map a "legacy" REST server using RESTEasy client.
The urls of this ws are mapped like this:
http://localhost/webservice/rest/server.php?wstoken=reallylongtokenhash&wsfunction=core_course_get_courses
The endpoint is always server.php, and the function to call is mapped using a queryparam.
#POST
#Path("/server.php")
#Produces("application/json")
List<Map<String, Object>> getCourses(
#QueryParam("wstoken") String token
, #QueryParam("wsfunction") String function
, #QueryParam("moodlewsrestformat") String format);
#POST
#Path("/server.php")
#Produces("application/json")
String createUser(
#QueryParam("wstoken") String token
, #QueryParam("wsfunction") String function
, #QueryParam("moodlewsrestformat") String format
, #Form User user);
which I call in this way
private static void getCourses() {
final MoodleRest client = ProxyFactory.create(MoodleRest.class, "http://localhost/webservice/rest/");
final List<Map<String, Object>> s = client.getCourses(token, "core_course_get_courses", "json");
System.out.println("s = " + s);
}
Let's ignore the fact that a "get_courses" method is mapped using a POST, and that the token are passed using the QueryParameter on this post, is it possible to avoid passing the function and the response format on every method? I would like to map it using the annotations.
I tried to write in directly into the #Path using
/server.php?function=core_course_get_courses
But obviously this is not the right way to proceed (plus, it doesn't work since it's escaped)
Maybe it would be better to use HttpServletRequest directly in your method and parse request parameters "by hand". I mean:
#POST
#Path("/server.php")
#Produces("application/json")
List<Map<String, Object>> getCourses(#Context HttpServletRequest request){
//parse request.getParameters()
}

PayPal's CallerServices Works on localhost but not server

My PayPal Direct script works perfect on my machine. Both nUnit tests and via a website on localhost. However this first line of code fails on my server and another server. (both full trust)
CallerServices caller = new CallerServices();
Message: The type initializer for 'com.paypal.sdk.core.soap.SOAPAPICaller' threw an exception.
Source: paypal_base
Stack Trace:
at com.paypal.sdk.core.soap.SOAPAPICaller..ctor()
at com.paypal.sdk.services.CallerServices..ctor()
at TS.Common.BusinessLogic.PaymentGateways.PayPalProController.CChargeCard(String paymentAmount, Order CurrentOrder, String creditCardType, String creditCardNumber, String CVV2, String expMonth, String expYear, PaymentActionCodeType paymentAction, Transaction& transaction)
at TS.Common.BusinessLogic.PaymentGateways.PayPalProController.ChargeCard(Order CurrentOrder, Decimal Amount, String CreditCardNum, String ExpMonth, String ExpYear, String SecurityNumber, Transaction& transaction)
at OrderController.SubmitCreditCardPayment(Order order, Decimal ChargeAmount, String CreditCardNum, String ExpMonth, String ExpYear, String Var, String CardType, Transaction& transaction)
at OrderController.SubmitOrder(Order order, Transaction& transaction, Nullable`1 GiftCertId, String CreditCardNum, String ExpMonth, String ExpYear, String Var, String CardType, String Culture)
at Checkout.btnOrder_Click(Object sender, EventArgs e) in d:\Inetpub\tickets\Checkout.aspx.cs:line 488
Add log4net.dll , if not put it in your bin folder and add reference. It works for me...
Add the reference to the log4net.dll with the specific version only. It will work