Javafx Hyperlink parameters on action - dynamic

Thank you for reading my question and apologies for the noobness
I am writing my first JavaFX application in which I have an array of hyperlinks which have latitude longitude (e.g. "42N 7E") in the text value of the hyperlink which is being updated every second from another Thread and updates the hyperlink text in the Main Thread. (This works fine)
public static void setPosLatLong(String posLatLong, int SID) {
Main.posLatLong[SID].setText(posLatLongValue);
}
I am trying to use the value in the hyperlink text when clicking on the hyperlink to dynamically change the destination URL with the latest latlong values... but I get the error 'local variables referenced from a lambda expression must be final or effectively final'
int SID = 'id of the hyperlink corresponding to a machine'
posLatLong[SID] = new Hyperlink();
posLatLong[SID].setOnAction((ActionEvent event) -> {
getHostServices().showDocument("http://maps.google.com/maps?z=17&q=" + posLatLong[SID].getText());
});
I have tried all kinds of ways to get around this but I am shamefully stuck. If anyone could point me in the right direction so that the last updated value in the hyperlink array is passed as a parameter when opening the browser it would be greatly appreciated.

I think I managed to find a solution myself so I'll post it in case it could be useful to someone
posLatLong[i].setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
String eventLatLong = "";
Object source = event.getSource();
if (source instanceof Hyperlink) {
Hyperlink link = (Hyperlink) source;
eventLatLong = link.getText();
}
getHostServices().showDocument("http://maps.google.com/maps?z=17&q=" + eventLatLong );
}
});
Tada !

Related

How to write an APEX #test for a picklist method?

I was searching for answears but I couldn't find it. It might be a beginner question, anyhow I am stuck.
What I am trying to write is a test in Apex. Basically the Apex code gets field names from one specific object. Each fieldname will be shown in a picklist, one after the other (that part is a LWC JS and HTML file).
So, only want to test the Apex for the moment.
I don't know how to check that a list contains 2 parameters, and those parameters are object and field. Then the values are correctly returned, and I don't know how to continue.
Here's the Apex class with the method, which I want to test.
public without sharing class LeadController {
public static List <String> getMultiPicklistValues(String objectType, String selectedField) {
List<String> plValues = new List<String>();
Schema.SObjectType convertToObj = Schema.getGlobalDescribe().get(objectType);
Schema.DescribeSObjectResult objDescribe = convertToObj.getDescribe();
Schema.DescribeFieldResult objFieldInfo = objDescribe.fields.getMap().get(selectedField).getDescribe();
List<Schema.PicklistEntry> picklistvalues = objFieldInfo.getPicklistValues();
for(Schema.PicklistEntry plv: picklistvalues) {
plValues.add(plv.getValue());
}
plValues.sort();
return plValues;
}
}
I welcome any answers.
Thank you!
This might be a decent start, just change the class name back to yours.
#isTest
public class Stack73155432Test {
#isTest
public static void testHappyFlow(){
List<String> picklistValues = Stack73155432.getMultiPicklistValues('Lead', 'LeadSource');
// these are just examples
System.assert(!picklistValues.isEmpty(), 'Should return something');
System.assert(picklistValues.size() > 5, 'At least 5 values? I dunno, whatever is right for your org');
System.assert(picklistValues[0] < picklistValues[1], 'Should be sorted alphabetically');
System.assert(picklistValues.contains('Web'), 'Or whatever values you have in the org');
}
#isTest
public static void testErrorFlow(){
// this is actually not too useful. You might want to catch this in your main code and throw AuraHandledExceptions?
try{
Stack73155432.getMultiPicklistValues('Account', 'AsdfNoSuchField');
System.assert(false, 'This should have thrown');
} catch(NullPointerException npe){
System.assert(npe.getMessage().startsWith('Attempt to de-reference a null object'), npe.getMessage());
}
}
}

How to attach pdf from trigger to an object?

I'm a bit lost trying to attach a pdf with populated values from an opportunity record
Here is the code:
Trigger:
trigger OpportunityTrigger on Opportunity (after insert)
if(trigger.isAfter && trigger.isUpdate) {
opportunityTriggerHelper.attachFileToOpportunityRecord(trigger.new);
}
Helper Class:
private void attachFileToOpportunityRecord(List<Opportunity> lstOpp) {
List<Id> oppListIdsForAttach = new List<Id>();
for(Opportunity opp : lstOpp) {
oppListIdsForAttach .add(opp.Id);
}
attachFileToOpportunities(oppListIdsForAttach);
}
#future(callout=true)
private static void attachFileToOppotunities(List<Id> OpportunityIds) {
List<Attachment> attachList = new List<Attachment>();
for(Id oppId : opportunityIds) {
OpportunityPdfController file = new OpportunityPdfController();
file.getData(oppId);
PageReference pdfPage = Page.PdfAttachmentForOpp;
blob pdfBody;
pdfBody = pdfPage.getContent();
Attachment attach = new Attachment();
attach.Body = pdfBody;
attach.Name = 'Pdf file';
attach.IsPrivate = false;
attach.ParenId = oppId;
attachList.add(attach);
}
insert attachList;
}
VF Page:
<apex:page controller="OpportunityPdfController" renderAs="pdf">
<apex:repeat value="{!pricingDetails}" var="pd">
<apex:outputText>{!pd.basePrice}</apex:outputText>
</apex:repeat>
</apex:page>
VF Page Controller:
public with sharing class OpportunityPdfController {
public List<PricingDetailWrapper> pricingDetails {get;set;}
public void getData(Id opportunityId) {
List<Pricing_Detail__c> pdList = [
SELECT basePrice
FROM Pricing_Detail__c
WHERE OpportunityId =: opportunityId
];
for(Pricing_Detail__c pd : pdList) {
PricingDetailWrapper pdw = new PricingDetailWrapper();
pdw.basePrice = pd.basePrice;
pricingDetails.add(pdw);
}
}
public class PricingDetailWrapper {
public String basePrice {get;set;}
}
}
The result is whenever I update an opportunity it attaches the corresponding pdf file but it is blank and if I add for example the following to vf page body: "<h1> hello World!</h1>" this works and shows as expected, but this is not happening to what I required above.
You didn't really pass the opportunity id to the VF page. And I doubt this actually works at all? If you manually access the VF page as /apex/PdfAttachmentForOpp?id=006... does it render the content ok? I'm assuming it doesn't.
Fixing the page
You didn't specify constructor so SF generates one for you, fine. I think you need to add something like
public OpportunityPdfController(){
if(ApexPages.currentPage() != null){
Id oppId = ApexPages.currentPage().getParameters().get('id');
System.debug(oppId);
getData(oppId);
}
}
Add this, try to access the page passing valid opp id and see if it renders ok, if right stuff shows in debug log. /apex/PdfAttachmentForOpp?id=006...
(VF page constructors are bigger topic, this might be simpler with standardController + extension class)
Fixing the callout
VF page (especially accessed as callout) will not share memory with the OpportunityPdfController controller you've created in the code. New object of this class will be created to support the page and your file will be ignored. You might try to make-do with some static variable holding current opportunity's id but it feels bit yucky.
In normal execute anonymous try if this returns correct pdf:
PageReference pdfPage = Page.PdfAttachmentForOpp;
pdfPage.getParameters().put('id', '006...');
Blob pdfBody = pdfPage.getContent();
System.debug(pdfBody.toString());
If it works - use similar trick in the actual code, pass the id as url parameter.

RazorEngine Error trying to send email

I have an MVC 4 application that sends out multiple emails. For example, I have an email template for submitting an order, a template for cancelling an order, etc...
I have an Email Service with multiple methods. My controller calls the Send method which looks like this:
public virtual void Send(List<string> recipients, string subject, string template, object data)
{
...
string html = GetContent(template, data);
...
}
The Send method calls GetContent, which is the method causing the problem:
private string GetContent(string template, object data)
{
string path = Path.Combine(BaseTemplatePath, string.Format("{0}{1}", template, ".html.cshtml"));
string content = File.ReadAllText(path);
return Engine.Razor.RunCompile(content, "htmlTemplate", null, data);
}
I am receiving the error:
The same key was already used for another template!
In my GetContent method should I add a new parameter for the TemplateKey and use that variable instead of always using htmlTemplate? Then the new order email template could have newOrderKey and CancelOrderKey for the email template being used to cancel an order?
Explanation
This happens because you use the same template key ("htmlTemplate") for multiple different templates.
Note that the way you currently have implemented GetContent you will run into multiple problems:
Even if you use a unique key, for example the template variable, you will trigger the exception when the templates are edited on disk.
Performance: You are reading the template file every time even when the template is already cached.
Solution:
Implement the ITemplateManager interface to manage your templates:
public class MyTemplateManager : ITemplateManager
{
private readonly string baseTemplatePath;
public MyTemplateManager(string basePath) {
baseTemplatePath = basePath;
}
public ITemplateSource Resolve(ITemplateKey key)
{
string template = key.Name;
string path = Path.Combine(baseTemplatePath, string.Format("{0}{1}", template, ".html.cshtml"));
string content = File.ReadAllText(path);
return new LoadedTemplateSource(content, path);
}
public ITemplateKey GetKey(string name, ResolveType resolveType, ITemplateKey context)
{
return new NameOnlyTemplateKey(name, resolveType, context);
}
public void AddDynamic(ITemplateKey key, ITemplateSource source)
{
throw new NotImplementedException("dynamic templates are not supported!");
}
}
Setup on startup:
var config = new TemplateServiceConfiguration();
config.Debug = true;
config.TemplateManager = new MyTemplateManager(BaseTemplatePath);
Engine.Razor = RazorEngineService.Create(config);
And use it:
// You don't really need this method anymore.
private string GetContent(string template, object data)
{
return Engine.Razor.RunCompile(template, null, data);
}
RazorEngine will now fix all the problems mentioned above internally. Notice how it is perfectly fine to use the name of the template as key, if in your scenario the name is all you need to identify a template (otherwise you cannot use NameOnlyTemplateKey and need to provide your own implementation).
Hope this helps.
(Disclaimer: Contributor of RazorEngine)

Abstraction with variables

So I'm taking a highschool online Java class and well my teacher doesn't help...
so we are learning about abstraction and I had already done this with my "alien" class that moves, he will face one way going forward and another going backward by switching two images... However when they showed the code in an example it seemed overcomplicated and I was wondering if I am just missing something.
My Code
private String avatarRight = "Alien.png";
private String avatarLeft = "Alien1.png";
/**
* Act - do whatever the Alien wants to do. This method is called whenever
* the 'Act' or 'Run' button gets pressed in the environment.
*/
public void act()
{
movement(avatarRight, avatarLeft);
gatherPart();
}
(Superclass containing movement method)
/**
* Sets up the movement keys and facing for the Object
*/
public void movement(String avatarRight,String avatarLeft)
{
if (atWorldEdge() == false)
{
if (Greenfoot.isKeyDown("w"))
{
setLocation(getX(), getY()-2);
}
if (Greenfoot.isKeyDown("d"))
{
setImage(avatarRight);
setLocation(getX()+2, getY());
}
if (Greenfoot.isKeyDown("s"))
{
setLocation(getX(), getY()+2);
}
if (Greenfoot.isKeyDown("a"))
{
setImage(avatarLeft);
setLocation(getX()-2, getY());
}
}
else
{
}
}
Their Code
{
private GreenfootImage image1;
private GreenfootImage image2;
private boolean isKeyDown;
private String key;
private String sound;
/**
* Create a Duke and initialize his two images. Link Duke to a specific keyboard
* key and sound.
*/
public Duke(String keyName, String soundFile)
{
key = keyName;
sound = soundFile
image1 = new GreenfootImage("Duke.png")
image3 = new GreenfootImage("duke2.png")
setImage(image1);
}
}
Where I just say avatarRight = "this image"
they say key = keyname
key = "key"
edit:
So the way the set it up and I set mine up initially was
private int rotation;
public Capsule(int rot)
{
rotation = rot
setRotation(rotation);
}
but the one below works perfectly fine, as far as I can tell. Is there any reason why I would do the above code rather than the one below
public Capsule(int rot)
{
setRotation(rot);
}
OK, based on the commentary I'm inclined to say you're not comparing the same things.
Where I just say avatarRight = "this image" they say key = keyname key
= "key"
That doesn't seem to be exactly accurate. Where you say
private String avatarRight = "Alien.png"; and
private String avatarLeft = "Alien1.png";
they have the png hard coded in the constructor as "Duke.png" and "duke2.png", which by the way contains an error because as far as I can see there's no image3.
So the keyName doesn't seem to directly map as you say it does. Perhaps you should investigate the code further to see how they use the key or provide equal code for both examples so we can further see the differences.
By looking at it perhaps there's a map somewhere and the key would be used to access the specific alien or other type of game object.
To address your edit.
Is there any reason why I would do the above code rather than the one
below
It's not possible to tell by that code if the reason has any value; it doesn't appear to by what you've shown. I can tell you that the reason I would do that is because I need that value elsewhere but not now. That could be for any number of reasons. You have to look at all the code available to you and see if they ever use that variable anywhere else without passing it in. Then you have found the reason or the lack there of.

Captcha in oracle adf project

I'm trying to use captcha as it's shown in this example:
http://www.oracle.com/technetwork/developer-tools/jdev/captcha-099103.html
And it works fine in .jspx page or in .jsff page fragment, but I have to place captcha onto the first page of taskflow, and there... it's not updated! /* I mean the button "can't read image" doesn't work */ I have no idea why. Can anybody help?
Actually, I figured out how to do it by myself:
we need captcha image binding in our bean and the resetting method:
private RichImage captchaImage;
public void setCaptchaImage(RichImage captchaImage) {
this.captchaImage = captchaImage;
}
public RichImage getCaptchaImage() {
return captchaImage;
}
public void resetCaptcha(ActionEvent actionEvent) {
captchaImage.setSource("/captchaservlet?rand=" +
String.valueOf(Math.random()));
AdfFacesContext.getCurrentInstance().addPartialTarget(captchaImage.getParent());
}
All, I didn't know how to do was adding parameter to "/captchaservlet"
And now it works fine :)
But the next problem appears: when returning to this page with captcha from the second one in task flow I need to refresh captcha image. Is there any method that is executed on page return or something?
Aaaaaaaaaaaand I found even more elegant solution: one should just set the source of the captcha image to this method using the expression builder:
public String getCaptchaSource() {
return "/captchaservlet?rand=" + String.valueOf(Math.random());
}
The button "Refresh", of course, should be set as a partial trigger for the image, as in the example.
And that's it :)