adding an object to a list in play framework - list

I am new to play, whenever I use list.add(Object) to the list and print the size of the list, it remains 0 !!!
My Method is to like a tutorial, it checks if the logged-in user has liked this tutorial before, if yes, it increments the likeCount of the tutorial by one, and add the tutorial to the like list of the user. If no, it renders that he already likes it.
since the tutorial is not saved in the list, I am not able to check if it is already liked or not !!!
Models:
#Entity
public class RegisteredUser extends Model {
public String name;
#ManyToMany
public List<Tutorial> contributedTutorials;
public RegisteredUser(String name) {
this.name = name;
this.likeList = newArrayList<Tutorial>();
this.save();
}
}
#Entity
public class Tutorial extends Model {
public String Title;
public int likeCount;
public Tutorial(String title) {
this.title = title;
this.likeCount = 0;
}
Controller:
public Tutorials extends Controller {
public static void likeTutorial() {
if (session.get("RegisteredUserId") != null && session.get("tutID") != null ) {
{
long uId = Long.parseLong(session.get("RegisteredUserId"));
RegisteredUser user = RegisteredUser.findById(uId);
long tId = Long.parseLong(session.get("tutID"));
Tutorial tut = Tutorial.findById(tId);
int x = tut.likeCount;
x++;
if (!(user.likeList.contains(tut)))
// to check that this user didn't like this tut before
{
Tutorial.em().createQuery("update Tutorial set likeCount ="+ x +" where id=" +tId).executeUpdate();
tut.refresh();
user.updateLikeList(tut); // THIS IS NOT WORKING!!!
renderText("You have successfully liked this Tutorial " + user.likeList.size());
}
}
renderText("Opps Something went Wrong!!");
}
}
}
The view :
Like

+You don't need to call the this.save() and this.likeList = newArrayList<Tutorial>(); in the constructor. Actually the latter is syntactically wrong.
+Passing the tutorial ID as a session variable is very wrong. You need to pass it as a GET parameter to the action.
+Replace your check with:
// to check that this user didn't like this tut before
if (! user.likeList.contains(tut)) {
// Tutorial.em().createQuery("update Tutorial set likeCount ="+ x +" where id=" +tId).executeUpdate();
// tut.refresh();
// user.updateLikeList(tut); // THIS IS NOT WORKING!!!
tut.likeCount++;
tut.save();
// Since it's a ManyToMany relationship, you only need to add it to one list and the other will reflect properly if mappedBy properly
user.likeList.add(tut); // note that the example you showed uses contributedTutorials not likeList
user.save();
renderText("You have successfully liked this Tutorial " + user.likeList.size());
}

I made all adjustments You mentioned above
And
The mapping in RegisteredUser Model
#ManyToMany
public List<Tutorial> likeList;
and I have added the mapping to Tutorial Model
#ManyToMany
public List<RegisteredUser> likersList;
and adjusted the method in the controller as follows
if (! user.likeList.contains(tut)) {
tut.likeCount++;
//tut.likersList.add(user); // however this raised an error too! at the next line
tut.save();
//as for the likeCount update, it has worked perfectly, Thank You
// Since it's a ManyToMany relationship, you only need to add it to one list and the other will reflect properly if mappedBy properly
//I have modified Model Tutorial as shown above and it didn't work too !
user.likeList.add(tut);
user.save(); // this raised an error!!
renderText("You have successfully liked this Tutorial " + user.likeList.size());
}

Related

How to test an Update class in apex

Hello I am new to apex and soql, I would like some help on my test class, below is the code i am having trouble with,
public class UpdateMyCard {
#AuraEnabled(cacheable=false)
public static Card__c updateCard(Double Amount){
String userId = UserInfo.getUserId();
Card__c myCard = [SELECT Id, Card_no__c, total_spend__c From Card__c Where OwnerId =:userId];
myCard.total_spend__c = myCard.total_spend__c + Amount;
try{
update myCard;
}catch (Exception e) {
System.debug('unable to update the record due to'+e.getMessage());
}
return myCard;
}
}
Test Class
#isTest
public static void updatecard(){
UpdateMyCard.updateCard(200);
}
Error:
System.QueryException: List has no rows for assignment to SObject
Your code assumes there's already a Card record for this user. And it's exactly 1 record (if you have 2 your query will fail). I'm not sure what's your business requirement. Is it guaranteed there will always be such record? Should the code try to create one on the fly if none found? You might have to make that "updateCard" bit more error-resistant. Is the total spend field marked as required? Because "null + 5 = exception"
But anyway - to fix your problem you need something like that in the test.
#isTest
public static void updatecard(){
Card__c = new Card__c(total_spend__c = 100);
insert c;
UpdateMyCard.updateCard(200);
c = [SELECT total_spend__c FROM Card__c WHERE Id = :c.Id];
System.assertEquals(300, c.total_spend__c);
}

APEX Test Class 0% code coverage

I am trying to deploy some code that does something simple, when the user clicks on the accept button, it checks a checkbox (I have a workflow set up on the checkbox) and then I need it to redirect me to a thank you page. At the moment I don't know if my code is correct so I need to get the test correct to test it.
My Apex class:
public class proposalCon {
ApexPages.StandardController stdCtrl;
Public List <PPM_Project__c> PPM_Project_List {get;set;}
public proposalCon(ApexPages.StandardController controller) {
stdCtrl= controller;
PPM_Project_List = [ select Short_Description__c from PPM_Project__c ];
}
public PageReference save(){
upsert PPM_Project_List;
PageReference reRend = new PageReference('/apex/final_approval_canvas_complete');
reRend.setRedirect(true);
return reRend;
}
}
And here is my test attempt:
#isTest
private class proposalConTest{
static testMethod void testProposalCon() {
// List of Message
List <PPM_Project__c> PPM_ProjectList = new List<PPM_Project__c>();
PPM_ProjectList.add(new PPM_Project__c (
Name = 'A Test' ,
Short_Description__c = 'Good Job',
Due_Date__c = system.today()+30,
Final_Design_Artwork__c ='http://proteusleadership.com/DE123'
));
PPM_ProjectList.add(new PPM_Project__c (
Name = 'A Test 2' ,
Short_Description__c = 'Good Job',
Due_Date__c = system.today()+30,
Final_Design_Artwork__c ='http://proteusleadership.com/DEf123'
));
insert PPM_ProjectList;
Account account = new Account(Name='Test Co Pty Ltd');
insert account;
Contact contact = new Contact(firstName='TestFN',LastName='TestLN',email='testfn.testln#test.com',AccountId=account.Id);
insert contact;
// ** Start Testing ***/
proposalCon controller = new proposalCon();
PageReference reRend = new PageReference('/apex/final_approval_canvas_complete');
reRend.setRedirect(true);
PPM_ProjectList = [ select Short_Description__c from PPM_Project__c ];
}
}
I have been trying with no luck and any help would be greatly appreciated.
Thank you.
Joe
You need to instantiate a Standard Controller (feeding it a list of PPM Projects) and then instantiate your custom controller extension - like this:
PPM_Project__c proj = new PPM_Project__c() //you may need further parameters here.
ApexPages.StandardController stdController = new apexPages.StandardController(proj);
proposalCon controller = new proposalCon (stdController);
Then you can save, rerender as you like. Let me know if this works - I haven't executed this code, but this is how I create my own controller extension tests.
This should at least compile. However, I think you may really want a StandardSetController.
The docs are here:
SalesforceDocs
To make a testmethod for the StandardSetController, use something like this:
//instantiate the ApexPages.StandardSetController with an array of projects
ApexPages.StandardSetController stdSetController = new ApexPages.StandardSetController(PPM_ProjectList);
//create custom controller with the StandardSetController as a param
ProposalCon ext = new ProposalCon(stdSetController);
This guy has more details on how to create a test method for a StandardSetController (and other controllers)

How can I override the test method name that appears on the TestNG report?

How can I override the test name that appears on the TestNG report? I want to override the name that appears in the middle column (currently shows as the method name). Is this even possible?
I tried to do it like this, but it didn't work.
public class EchApiTest1 extends TestBase {
...
#BeforeTest
public void setUp() {
restClient = new RestClientPost();
this.setTestName( "ech: XXXXXX" );
}
And, the base class:
import org.testng.ITest;
public class TestBase implements ITest {
String testName = "";
#Override
public String getTestName() {
return this.testName;
}
public void setTestName( String name ) {
this.testName = name;
}
}
NOTE: The above code does work when I am viewing the report detail in the Jenkins TestNG plugin report, which shows the overridden test name as a string called "Instance Name:" at the beginning of the Reporter log output. Why, in this case, WHY does a "setTestName()" method alter a string labeled "Instance Name" in the report?
One answer I found had a suggestion like this but I don't know how to pass an ITestResult arg to a AfterMethod method:
#AfterMethod
public void setResultTestName( ITestResult result ) {
try {
BaseTestMethod bm = (BaseTestMethod)result.getMethod();
Field f = bm.getClass().getSuperclass().getDeclaredField("m_methodName");
f.setAccessible(true);
f.set( bm, bm.getMethodName() + "." + your_customized_name );
} catch ( Exception ex ) {
Reporter.log( "ex" + ex.getMessage() );
}
Thoughts?
Please find following code for set custom name of testcase in TestNG reports.
Following features are available in this code.
Dynamic execution on same test-case in multiple time
Set custom test-case name for reports
Set parallel execution of multiple test-cases execution
import java.lang.reflect.Field;
import org.testng.ITest;
import org.testng.ITestResult;
import org.testng.Reporter;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Factory;
import org.testng.annotations.Test;
import org.testng.internal.BaseTestMethod;
import com.test.data.ServiceProcessData;
public class ServiceTest implements ITest {
protected ServiceProcessData serviceProcessData;
protected String testCaseName = "";
#Test
public void executeServiceTest() {
System.out.println(this.serviceProcessData.toString());
}
#Factory(dataProvider = "processDataList")
public RiskServiceTest(ServiceProcessData serviceProcessData) {
this.serviceProcessData = serviceProcessData;
}
#DataProvider(name = "processDataList", parallel = true)
public static Object[] getProcessDataList() {
Object[] serviceProcessDataList = new Object[0];
//Set data in serviceProcessDataList
return serviceProcessDataList;
}
#Override
public String getTestName() {
this.testCaseName = "User custom testcase name";
// this.testCaseName = this.serviceProcessData.getTestCaseCustomName();
return this.testCaseName;
}
#AfterMethod(alwaysRun = true)
public void setResultTestName(ITestResult result) {
try {
BaseTestMethod baseTestMethod = (BaseTestMethod) result.getMethod();
Field f = baseTestMethod.getClass().getSuperclass().getDeclaredField("m_methodName");
f.setAccessible(true);
f.set(baseTestMethod, this.testCaseName);
} catch (Exception e) {
ErrorMessageHelper.getInstance().setErrorMessage(e);
Reporter.log("Exception : " + e.getMessage());
}
}}
Thanks
I found a "workaround" but I am hoping for a better answer. I want to be able to show this "test name" OR "instance name" value on the HTML report (not just within the Reporter.log output) and I am starting to think its not possible :
#Test(dataProvider = "restdata2")
public void testGetNameFromResponse( TestArguments testArgs ) {
this.setTestName( "ech: " + testArgs.getTestName() );
Reporter.log( getTestName() ); // this magic shows test name on report
....
With this workaround, the user can now identify which test it was by looking at the Reporter.log output but I still wish the name was more prominant.
I suspect the answer lies in writing a TestListenerAdapter that somehow overrides the ITestResult.getTestNameMethod() method? That is the holy grail I am looking for.
The ‘result’ object will automatically pass in the method setResultTestName( ITestResult result )
Make sure you put alwaysRun=true like the following when you have groups defined in your test class otherwise “AfterMethod” will not be excuted.
#AfterMethod (alwaysRun=true)

Neo4j: spring-data-neo4j,how to cast result to my type class?

I have insert some node into Neo4j DB.And I want to select some node from database and cast it to specific class.
Here are some code about the problem:
class Service {
Neo4jTemplate neo4jTemplate
#Transactional
def find() {
def id1 = 11
//Knowledge k = neo4jTemplate.findOne(1, Knowledge)
Result result = neo4jTemplate.query("start n=node(11) return ID(n),n.name,n.age;", null)
//how to cast the result to User class
println "the tpye of result called User is "+ result.to(User.class).is(cn.edu.bnuz.itc.bok.sub2.User.class)
}
}
The detail about node like :
+-------------------------------------------------------------------------+
| Node[11]{career:"programmer",name:"kelvin",age:35,introduce:"lazy doy"} |
+-------------------------------------------------------------------------+
#NodeEntity
class User {
#GraphId
Long id;
String name;
int age;
}
I just want get the node's id, name, age from db and put it into a User class.
But it failed many time with many method.
Here I have encounter a problem which is :How can I cast the result to my target class? I have try many method to cast but fail finally.Thank you for you attention.
Return the user node from the query and call the to method of the returned Result with the desired class as argument:
Result result = neo4jTemplate.query("start n=node(11) return n", null);
for(User u : result.to(User.class)) {
doSomethingWith(u);
}
You may want to consider using repositories that support cypher queries like:
public interface UserRepository extends GraphRepository<User> {
#Query("start n=node(11) return n")
Iterable<User> getUser11();
}

How to get the large picture from feed with graph api?

When loading the Facebook feeds from one page, if a picture exist in the feed, I want to display the large picture.
How can I get with the graph API ? The picture link in the feed is not the large one.
Thanks.
The Graph API photo object has a picture connection (similar to that the user object has):
“The album-sized view of the photo. […] Returns: HTTP 302 redirect to the URL of the picture.”
So requesting https://graph.facebook.com/{object-id-from-feed}/picture will redirect you to the album-sized version of the photo immediately. (Usefull not only for displaying it in a browser, but also if f.e. you want to download the image to your server, using cURL with follow_redirect option set.)
Edit:
Beginning with API v2.3, the /picture edge for feed posts is deprecated.
However, as a field the picture can still be requested – but it will be a small one.
But full_picture is available as well.
So /{object-id-from-feed}?fields=picture,full_picture can be used to request those, or they can be requested directly with the rest of feed data, like this /page-id/feed?fields=picture,full_picture,… (additional fields, such as message etc., must be specified the same way.)
What worked for me :
getting the picture link from the feed and replacing "_s.jpg" with "_n.jpg"
OK, I found a better way. When you retrieve a feed with the graph API, any feed item with a type of photo will have a field called object_id, which is not there for plain status type items. Query the Graph API with that ID, e.g. https://graph.facebook.com/1234567890. Note that the object ID isn't an underscore-separated value like the main ID of that feed item is.
The result of the object_id query will be a new JSON dictionary, where you will have a source attribute containing a URL for an image that has so far been big enough for my needs.
There is additionally an images array that contains more image URLs for different sizes of the image, but the sizes there don't seem to be predictable, and don't all actually correspond to the physical dimensions of the image behind that URL.
I still wish there was a way to do this with a single Graph API call, but it doesn't look like there is one.
For high res image links from:
Link posts
Video posts
Photo posts
I use the following:
Note: The reason I give the _s -> _o hack precedence over the object_id/picture approach is because the object_id approach was not returning results for all images.
var picture = result.picture;
if (picture) {
if (result.type === 'photo') {
if (picture.indexOf('_s') !== -1) {
console.log('CONVERTING');
picture = picture.replace(/_s/, '_o');
} else if (result.object_id) {
picture = 'https://graph.facebook.com/' + result.object_id + '/picture?width=9999&height=9999';
}
} else {
var qps = result.picture.split('&');
for (var i = 0; i < qps.length; i++) {
var qp = qps[i];
var matches = qp.match(/(url=|src=)/gi);
if (matches && matches.length > 0) picture = decodeURIComponent(qp.split(matches[0])[1]);
}
}
}
This is a new method to get a big image. it was born after the previews method doesn't works
/**
* return a big url of facebook
* works onky for type PHOTO
* #param picture
* #param is a post type link
* #return url of image
*/
#Transactional
public String getBigImageByFacebookPicture(String pictrue,Boolean link){
if(link && pictrue.contains("url=http")){
String url = pictrue.substring(pictrue.indexOf("url=") + 4);
try {
url = java.net.URLDecoder.decode(url, "UTF-8");
} catch (UnsupportedEncodingException e) {
StringBuffer sb = new StringBuffer("Big image for Facebook link not found: ");
sb.append(link);
loggerTakePost.error(sb.toString());
return null;
}
return url;
}else{
try {
Document doc = Jsoup.connect(pictrue).get();
return doc.select("#fbPhotoImage").get(0).attr("src");
} catch (Exception e) {
StringBuffer sb = new StringBuffer("Big image for Facebook link not found: ");
sb.append(link);
loggerTakePost.error(sb.toString());
return null;
}
}
}
Enjoy your large image :)
Actually, you need two different solutions to fully fix this.
1] https://graph.facebook.com/{object_id}/picture
This solution works fine for images and videos posted to Facebook, but sadly, it returns small images in case the original image file was not uploaded to Facebook directly. (When posting a link to another site on your page for example).
2] The Facebook Graph API provides a way to get the full images in the feed itself for those external links. If you add 'full_picture' to the fields like in this example below when calling the API, you will be provided a link to the higher resolution version.
https://graph.facebook.com/your_facebook_id/posts?fields=id,link,full_picture,description,name&access_token=123456
Combining these two solutions I ended up filtering the input in PHP as follows:
if ( isset( $post['object_id'] ) ){
$image_url = 'https://graph.facebook.com/'.$post['object_id'].'/picture';
}else if ( isset( $post['full_picture'] ) ) {
$image_url = $post['full_picture'];
}else{
$image_url = '';
}
See: http://api-portal.anypoint.mulesoft.com/facebook/api/facebook-graph-api/docs/reference/pictures
Just put "?type=large" after the URL to get the big picture.
Thanks to #mattdlockyer for the JS solution. Here is a similar thing in PHP:
$posts = $facebook->api('/[page]/posts/', 'get');
foreach($posts['data'] as $post)
{
if(stristr(#$post['picture'], '_s.'))
{
$post['picture'] = str_replace('_s.', '_n.', #$post['picture']);
}
if(stristr(#$post['picture'], 'url='))
{
parse_str($post['picture'], $picturearr);
if($picturearr['url'])
$post['picture'] = $picturearr['url'];
}
//do more stuff with $post and $post['picture'] ...
}
After positive comment from #Lachezar Todorov I decided to post my current approach (including paging and using Json.NET ;):
try
{
FacebookClient fbClient = new FacebookClient(HttpContext.Current.Session[SessionFacebookAccessToken].ToString());
JObject posts = JObject.Parse(fbClient.Get(String.Format("/{0}/posts?fields=message,picture,link,attachments", FacebookPageId)).ToString());
JArray newsItems = (JArray)posts["data"];
List<NewsItem> result = new List<NewsItem>();
while (newsItems.Count > 0)
{
result.AddRange(GetItemsFromJsonData(newsItems));
if (result.Count > MaxNewsItems)
{
result.RemoveRange(MaxNewsItems, result.Count - MaxNewsItems);
break;
}
JToken paging = posts["paging"];
if (paging != null)
{
if (paging["next"] != null)
{
posts = JObject.Parse(fbClient.Get(paging.Value<String>("next")).ToString());
newsItems = (JArray)posts["data"];
}
}
}
return result;
}
And the helper method to retieve individual items:
private static IEnumerable<NewsItem> GetItemsFromJsonData(IEnumerable<JToken> items)
{
List<NewsItem> newsItems = new List<NewsItem>();
foreach (JToken item in items.Where(item => item["message"] != null))
{
NewsItem ni = new NewsItem
{
Message = item.Value<String>("message"),
DateTimeCreation = item.Value<DateTime?>("created_time"),
Link = item.Value<String>("link"),
Thumbnail = item.Value<String>("picture"),
// http://stackoverflow.com/questions/28319242/simplify-looking-up-nested-json-values-with-json-net/28359155#28359155
Image = (String)item.SelectToken("attachments.data[0].media.image.src") ?? (String)item.SelectToken("attachments.data[0].subattachments.data[0].media.image.src")
};
newsItems.Add(ni);
}
return newsItems;
}
NewsItem class I use:
public class NewsItem
{
public String Message { get; set; }
public DateTime? DateTimeCreation { get; set; }
public String Link { get; set; }
public String Thumbnail { get; set; }
public String Image { get; set; }
}