So in a lot of AWS Lambda tutorials, it teaches us to write a few lines of code, package it, and upload it.
Is there a code example where you can just trigger/call the lambda in your current project using the ARN or something? My current project is huge and I can't/it's not preferable to upload the function package to AWS Lambda, I just want to trigger it in my current code.
One link I found is: https://aws.amazon.com/blogs/developer/invoking-aws-lambda-functions-from-java/ but it does not work for me so far.
Apologies if it's been asked already; I didn't find anything useful to me.
EDIT:
My problem is the lambda function only gets invoked because I've uploaded it as a JAR (ie. its not a part of my main project, I just did it as a test), but I want to write the code to be invoked in my main project. I don't know how to invoke the lambda in my Java code. Like #MaxPower said, perhaps I have this all wrong and this is not possible.
What I do is create an interface with the #LambdaFunction annotation.
public interface Foo {
#LambdaFunction(functionName = "LambdaName")
OutputObject doFoo(InputObject inputObject);
}
Then in the class that is to call the lambda I make a Lambda client
private final Foo fooCaller;
RunTest() {
ProfileCredentialsProvider lambdaCredentialsProvider = new ProfileCredentialsProvider("lambda");
AWSLambdaClientBuilder builder = AWSLambdaClientBuilder.standard().withCredentials(lambdaCredentialsProvider);
builder.setRegion("us-east-1");
AWSLambda awsLambda = builder.build();
LambdaInvokerFactory.Builder lambdaBuilder = LambdaInvokerFactory.builder();
lambdaBuilder.lambdaClient(awsLambda);
fooCaller = lambdaBuilder.build(Foo.class);
}
then when you want to call the lambda
fooCaller.doFoo();
Related
I've imported a library into my code that uses Sealed Classes as Error Handling. The Library is written in Kotlin, and my code is in Java. Other than this line, things have gone okay.
Code Example of what I've tried to even hold the Resource:
String dogID = "1234";
DogClient dogClient = new dogClient(); //params not important.
Resource<DogDto> dogDtoResource = dogClient.fetchDog(dogID); //Problem Statement
The dogClient.fetchDog(String id) method uses a sealed class called Resource where it uses data classes to handle errors. When I try to do the above, it says it cannot access Kotlin.coroutines.Continuation.
Resource in T code:
sealed class Resource<in T> {
data class Success<T>(val data: T) : Resource<T>()
data class Error(val exception: Throwable, val statusCode: Int?) : Resource<Any>()
}
I need to access the data on Success, and know when it throws an Error. The code in Kotlin would work something like this:
when(dogClient.fetchDog(dogId)) {
is Resource.Success -> result.data;
is Resource.Error -> throw new Exception();
I am completely lost on how to translate this to Java and haven't found any articles/documentation to help me.
it says it cannot access Kotlin.coroutines.Continuation
The problem is probably not the Resource sealed class then, but rather the fetchDog function you're trying to call is most likely a suspend function in Kotlin (using Kotlin coroutines).
You can check this other answer for this specific problem. It basically boils down to providing a non-suspend function from the Kotlin code, which you will be able to call from Java.
If you cannot modify the library, you can add a simple Kotlin file to your project to write this "bridge" function (but this means you'll need to setup Kotlin compilation in your project).
As of now, I have an API and an existing AWS Lambda that more or less have the same functionality. What I was trying to do, was instead of performing the same task in each project, I was attempting to have the API itself imply trigger the lambda. At the moment, sending it data isn't my primary concern, but that would be something I would try to do. That said, in Java, if you have all the credentials, the lambda name, and so on, is it possible to trigger an AWS Lambda locally and eventually through an API?
I've been going through a few solutions now, but it seems that many of them involve redeploying the lambda, or making a new one altogether. At the moment, I've been using these resources, A, B, C, and D.
My current function in my API looks something like this. The one in my lambda, let's call it foobar-lambda for now, is pretty much the same.
public Entity<Foos> Foos(#RequestHeader(value= "ApiKey", required = false) String apiKey,
#RequestParam String data) {
Foos foos = FoosService.getFoos(data);
Entity<Foos> response = null;
if (foos != null) {
response = Entity.ok().body(foos);
} else {
response = new Entity<>(HttpStatus.NOT_FOUND);
}
return response;
}
What I'd like to change this to, is something like this:
void Entity<Foos> Foos(#RequestHeader(value= "ApiKey", required = false) String apiKey,
#RequestParam String data) {
triggerAndSend("foobar-lambda",data);
}
So, in this context, I'm trying to figure out exactly how to create the void triggerAndSend(String lambdaTarget, Integer... data) function. Ideally, I'd run this, and I'd be able to see that my lambda was triggered. Do I have to add an additional trigger in my Lambda to catch these? Is it possible, and if so, does anyone have any recommendations for how I can accomplish my goal?
This AWS Blog post describes one way to do what you're describing: Invoking AWS Lambda Functions from Java. It involves defining a Plain Old Java Object for the return value and an interface for the lambda function.
We have developed some lambda function and deployed on AWS which are working fine,
Anyhow, client is now planning for AZURE.
They may even switch back to AWS or any other vendor in future.
We have a separate maven project for AWS related stuff.
Hence, our business logic and classes remains same.
What I have done is created a maven project and added individual lambda functions to this project as dependencies.
Then made a factory class which will get impl based on property AZURE or AWS(using class.forName and reflection).
SO, I can switch to Azure by just removing maven dependency and adding AZURE dependency.
According to picture my plan was to create new AzureUtils and AzureWrapper project and Directly use Azure Cloud, by switching cloud in cloudFactory which is present in Generic utils and that would even work hopefully (Not tested) AWS is working anyhow like that.
Now the problem is client does not want everything packed up in 1 jar, i.e no no to all lambdas in a single jar. He want some layer where the switching should take place.
Now Which design patter would be useful, what would be the approach.
Currently my Lambda function looks like below
public class Hello implements RequestHandler<S3Event, Context > {
public String handleRequest(S3Event s3event, Context context) {
.................
call to business processor as in diag
}
}
And azure function looks somewhat like a simple class with annotations
public class Function {
#FunctionName("hello")
public HttpResponseMessage run(
#HttpTrigger(name = "req", methods = { HttpMethod.GET, HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
final ExecutionContext context) {
context.getLogger().info("Java HTTP trigger processed a request.");
// Parse query parameter
String query = request.getQueryParameters().get("name");
String name = request.getBody().orElse(query);
if (name != null) {
call to business processor as in diagram
}
}
}
After all this I have only 2 questions
I would like to know first if the design in diagram is right thing to do.
And what my client is asking for a wrapper something magical which should handle both type of cloud implementations. is this even possible?
if possible guide me in right direction
Any help is greatly appreciated.
about you secound question how to handle both type of cloud, please check this 3rd part solution serverless.com. It's a company that create own serverless wrapper, so that you can be free of vendor lock
I have this method that I am using in a NetBeans plugin:
public static SourceCodeFile getCurrentlyOpenedFile() {
MainProjectManager mainProjectManager = new MainProjectManager();
Project openedProject = mainProjectManager.getMainProject();
/* Get Java file currently displaying in the IDE if there is an opened project */
if (openedProject != null) {
TopComponent activeTC = TopComponent.getRegistry().getActivated();
DataObject dataLookup = activeTC.getLookup().lookup(DataObject.class);
File file = FileUtil.toFile(dataLookup.getPrimaryFile()); // Currently opened file
// Check if the opened file is a Java file
if (FilenameUtils.getExtension(file.getAbsoluteFile().getAbsolutePath()).equalsIgnoreCase("java")) {
return new SourceCodeFile(file);
} else {
return null;
}
} else {
return null;
}
}
Basically, using NetBeans API, it detects the file currently opened by the user in the IDE. Then, it loads it and creates a SourceCodeFile object out of it.
Now I want to unit test this method using JUnit. The problem is that I don't know how to test it.
Since it doesn't receive any argument as parameter, I can't test how it behaves given wrong arguments. I also thought about trying to manipulate openedProject in order to test the method behaviour given some different values to that object, but as far as I'm concernet, I can't manipulate a variable in JUnit that way. I also cannot check what the method returns, because the unit test will always return null, since it doesn't detect any opened file in NetBeans.
So, my question is: how can I approach the unit testing of this method?
Well, your method does take parameters, "between the lines":
MainProjectManager mainProjectManager = new MainProjectManager();
Project openedProject = mainProjectManager.getMainProject();
basically fetches the object to work on.
So the first step would be to change that method signature, to:
public static SourceCodeFile getCurrentlyOpenedFile(Project project) {
...
Of course, that object isn't used, except for that null check. So the next level would be to have a distinct method like
SourceCodeFile lookup(DataObject dataLookup) {
In other words: your real problem is that you wrote hard-to-test code. The "default" answer is: you have to change your production code, to make easier to test.
For example by ripping it apart, and putting all the different aspects into smaller helper methods.
You see, that last method lookup(), that one takes a parameter, and now it becomes (somehow) possible to think up test cases for this. Probably you will have to use a mocking framework such as Mockito to pass mocked instances of that DataObject class within your test code.
Long story short: there are no detours here. You can't test your code (in reasonable ways) as it is currently structured. Re-structure your production code, then all your ideas about "when I pass X, then Y should happen" can work out.
Disclaimer: yes, theoretically, you could test the above code, by heavily relying on frameworks like PowerMock(ito) or JMockit. These frameworks allow you to contol (mock) calls to static methods, or to new(). So they would give you full control over everything in your method. But that would basically force your tests to know everything that is going on in the method under test. Which is a really bad thing.
I'm customizing a PLM Windchill Workflow, which provides a mechanism to execute java code snippets. Unfortunately, they are 'inserted' into prepared service's method, which means that there is no way to import classes, so I have to include full package names to use it. Don't try to understand the snippet below, just look how does it looks like:
wt.fc.QueryResult activities = wt.fc.PersistenceHelper.manager.find((wt.pds.StatementSpec) activitiesQuery);
while (activities.hasMoreElements()) {
wt.workflow.work.WfAssignedActivity activity = (wt.workflow.work.WfAssignedActivity) activities.nextElement();
if(activity.getDisplayIdentifier().toString().equals("Analyze Image Request")){
java.util.List<wt.workflow.work.WorkItem> workItems = wt.workflow.status.WfWorkflowStatusHelper.service.getWorkItems(activity);
for (wt.workflow.work.WorkItem workItem : workItems){
String action = workItem.getActionPerformed();
if(action != null && action.equals("Accepted")){
wt.org.WTPrincipalReference approver = workItem.getOwnership().getOwner();
n_approver = approver.getFullName() + " ("+approver.getDisplayName()+")";
wt.fc.collections.WTHashSet approverSet = new wt.fc.collections.WTHashSet(java.util.Arrays.asList(approver));
wt.project.Role role = wt.project.Role.toRole("APPROVER");
com.ptc.windchill.pdmlink.change.server.impl.WorkflowProcessHelper.setChangeItemParticipants(report, role, approverSet);
break;
}
}
break;
}
}
And my question is - how to make this code any more readable? Of course there is no way to import classes inside the method, there is even no way to divide this snippet into separate methods (as it is 'pasted' into one) so I'm looking for other ideas.
One option to make the code more readable would be to separate chained method/property calls across multiple lines.
For example, this line:
wt.project.Role role = wt.project.Role.toRole("APPROVER");
could be rewritten as:
wt.project.Role role = wt
.project
.Role
.toRole("APPROVER");
You can call this complete code from a Customized Java class.
You just have to call your class and take the final parameters required from the Java class to make it more readable.
If you need multiple outputs write multiple methods in Java class and call them in workflow expression.
You can't.
Workflows expressions are methods bodies.
A statement like
wt.fc.QueryResult activities = wt.fc.PersistenceHelper.manager.find((wt.pds.StatementSpec) activitiesQuery);
ends in a class under $WT_HOME/codebase/wt/workflow/expr/
with a method :
public static Object executemethod_1(Object[] var0, Object[] var1) throws Exception {
wt.fc.QueryResult activities = wt.fc.PersistenceHelper.manager.find((wt.pds.StatementSpec) activitiesQuery);
// some generated code to handle variables...
}
So, you can't use import.
However :
If you have a PDMLink version greater than 10,
You can externalize workflow expression
http://support.ptc.com/cs/help/windchill_hc/wc100_hc/index.jspx?id=WFTemplateExtExpression&action=show
This create a java class under /codebase/ext/wt/workflow/externalize
Then you can do what you want, but you'll have to compile these classes, and do a stop/start in case of modifications.
Basically, it's nothing more than calling external code from the expression, so I don't use it a lot...