I am attempting to retrieve the credentials for my Google service account with the following code:
package function
import com.amazonaws.services.lambda.runtime.Context
import com.amazonaws.services.lambda.runtime.LambdaLogger
import com.amazonaws.services.lambda.runtime.RequestHandler
import pojo.Request
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential
import com.google.api.services.sqladmin.SQLAdminScopes
import pojo.Response
class GoogleAuth implements RequestHandler<Request, Response> {
private LambdaLogger logger
#Override
Response handleRequest(Request input, Context context) {
logger = context.getLogger()
ClassLoader classLoader = getClass().getClassLoader()
File jsonCredentials = new File(classLoader.getResource("leads-cloud-function-service-account.json").getFile())
FileInputStream fis = new FileInputStream(jsonCredentials)
GoogleCredential credential = GoogleCredential.fromStream(fis).createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN))
credential.getClientAuthentication()
println("Thai test" + credential.getExpirationTimeMilliseconds())
print("This is the credential" + credential.getAccessToken())
return (new Response())
}
}
The information about the milliseconds for expiration and the AccessToken are null. Has anyone ever experienced this?
So I have resolved this myself by adding before the getToken the following command:
credential.refreshToken()
This is not properly documented in google's website but after adding it, this worked perfectly and the results are displayed with actual values.
Some other error I faced was the "com.google.common.io.ByteStreams.exhaust(Ljava/io/InputStream;)J", in order to resolve it I had to correct the dependency I was using to this one:
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.31.1</version>
</dependency>
so, keep on mind that too!
Related
I am using QAF Webservice support for API automation. I have a case where a GET request has a body present. If I pass the request as either using properties file or xml file, on executing I am getting 404 not found response. If the GET request does not have a body present, it works fine in that scenario without any issues. But not with GET request having a body. Upon debugging, found that jersey client API at the end changes the request from GET to POST if a GET request has a body. Please let me know on how to handle this scenario using QAF WebService.
Thanks,
You can use apache HttpClient that will allow to have body with get request. In order to use apache HttpClient, you need to provide implementation of RestClientFactory and register using property rest.client.impl.
Here is the sample code from the qaf users group.
package qaf.example.tests;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import com.qmetry.qaf.automation.ws.rest.RestClientFactory;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientHandler;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.client.apache.ApacheHttpClient;
import com.sun.jersey.client.apache.ApacheHttpClientHandler;
import com.sun.jersey.client.apache.config.DefaultApacheHttpClientConfig;
/**
* #author chirag
*
*/
public class ApacheClientProvider extends RestClientFactory {
#Override
protected Client createClient() {
MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
connectionManager.getParams().setConnectionTimeout(5000);
connectionManager.getParams().setSoTimeout(1000);
connectionManager.getParams().setDefaultMaxConnectionsPerHost(10);
HttpClient httpClient = new HttpClient(connectionManager);
ApacheHttpClientHandler clientHandler = new ApacheHttpClientHandler(httpClient);
ClientHandler root = new ApacheHttpClient(clientHandler );
ClientConfig config = new DefaultApacheHttpClientConfig();
Client client = new Client(root, config);
return client;
}
}
In order to use it, register your class using rest.client.impl property, in above case:
rest.client.impl=qaf.example.tests.ApacheClientProvider
I am trying to run a sample feature file with a couple cucumber scenarios, but when i run them i get that i did not implement the step definition, but i actually did, i have a folder called stepDefinitions and inside a java class called StepDefinition, where i wrote the steps
Testing started at 20:14 ...
Undefined scenarios:
/home/adrianjimenez/IdeaProjects/RestAssured/src/test/java/RestAssuredFramework/features/fileValidations.feature:13 # Verify if Place is being Successfully added using AddPlaceAPI
/home/adrianjimenez/IdeaProjects/RestAssured/src/test/java/RestAssuredFramework/features/fileValidations.feature:17 # Verify if Delete Place functionality is working
2 Scenarios (2 undefined)
10 Steps (10 undefined)
0m0.536s
You can implement missing steps with the snippets below:
#Given("Add Place Payload with {string} {string} {string}")
public void add_Place_Payload_with(String string, String string2, String string3) {
// Write code here that turns the phrase above into concrete actions
throw new cucumber.api.PendingException();
}
#When("user calls {string} with {string} http request")
public void user_calls_with_http_request(String string, String string2) {
// Write code here that turns the phrase above into concrete actions
throw new cucumber.api.PendingException();
}
#Then("the API call got success with status code {int}")
public void the_API_call_got_success_with_status_code(Integer int1) {
// Write code here that turns the phrase above into concrete actions
throw new cucumber.api.PendingException();
}
#Then("{string} in response body is {string}")
public void in_response_body_is(String string, String string2) {
// Write code here that turns the phrase above into concrete actions
throw new cucumber.api.PendingException();
}
#Then("verify place_Id created maps to {string} using {string}")
public void verify_place_Id_created_maps_to_using(String string, String string2) {
// Write code here that turns the phrase above into concrete actions
throw new cucumber.api.PendingException();
}
#Given("DeletePlace Payload")
public void deleteplace_Payload() {
// Write code here that turns the phrase above into concrete actions
throw new cucumber.api.PendingException();
}
Process finished with exit code 0
But i actually implemented the steps so i do not understand what is happening, these are the steps i have implemented.
package RestAssuredFramework.stepDefinitions;
import RestAssuredFramework.resources.APIResources;
import RestAssuredFramework.resources.TestDataBuilder;
import RestAssuredFramework.resources.Utils;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.path.json.JsonPath;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.io.IOException;
import static io.restassured.RestAssured.given;
import static org.junit.Assert.assertEquals;
public class StepDefinition extends Utils {
RequestSpecification res;
String responseString;
static String place_id;
ResponseSpecification resspec;
Response response;
TestDataBuilder testDataBuilder = new TestDataBuilder();
JsonPath jsonPath;
#Given("Add Place Payload with {string} {string} {string}")
public void add_Place_Payload_with(String name, String language, String address) throws IOException {
// Write code here that turns the phrase above into concrete actions
res=given().spec(requestSpecification())
.body(testDataBuilder.addPlacePayload(name,language,address));
}
#When("user calls {string} with {string} http request")
public void user_calls_with_http_request(String resource, String method) {
// Write code here that turns the phrase above into concrete actions
//constructor will be called with value of resource which you pass
APIResources resourceAPI=APIResources.valueOf(resource);
System.out.println(resourceAPI.getResource());
resspec =new ResponseSpecBuilder().expectStatusCode(200).expectContentType(ContentType.JSON).build();
if(method.equalsIgnoreCase("POST"))
response =res.when().post(resourceAPI.getResource());
else if(method.equalsIgnoreCase("GET"))
response =res.when().get(resourceAPI.getResource());
}
#Then("the API call got success with status code {int}")
public void the_API_call_got_success_with_status_code(Integer int1) {
// Write code here that turns the phrase above into concrete actions
assertEquals(response.getStatusCode(),200);
}
#Then("{string} in response body is {string}")
public void in_response_body_is(String keyValue, String Expectedvalue) {
// Write code here that turns the phrase above into concrete actions
assertEquals(getJsonPath(response,keyValue),Expectedvalue);
}
#Then("verify place_Id created maps to {string} using {string}")
public void verify_place_Id_created_maps_to_using(String expectedName, String resource) throws IOException {
// requestSpec
place_id=getJsonPath(response,"place_id");
res=given().spec(requestSpecification()).queryParam("place_id",place_id);
user_calls_with_http_request(resource,"GET");
String actualName=getJsonPath(response,"name");
assertEquals(actualName,expectedName);
}
//delete scneario
#Given("DeletePlace Payload")
public void deleteplace_Payload() throws IOException {
// Write code here that turns the phrase above into concrete actions
res =given().spec(requestSpecification()).body(testDataBuilder.deletePlacePayload(place_id));
}
}
and this is my feature file
Feature: Validating Place API's
#AddPlace #Regression
Scenario Outline: Verify if Place is being Successfully added using AddPlaceAPI
Given Add Place Payload with "<name>" "<language>" "<address>"
When user calls "AddPlaceAPI" with "POST" http request
Then the API call got success with status code 200
And "status" in response body is "OK"
And "scope" in response body is "APP"
And verify place_Id created maps to "<name>" using "getPlaceAPI"
Examples:
|name | language |address |
|peter | Spanish |Aguascalientes, st|
# |BBhouse | Spanish |Sea cross center |
#DeletePlace #Regression
Scenario: Verify if Delete Place functionality is working
Given DeletePlace Payload
When user calls "deletePlaceAPI" with "POST" http request
Then the API call got success with status code 200
And "status" in response body is "OK"
intellij version
IntelliJ IDEA 2019.3.2 (Community Edition)
Build #IC-193.6015.39, built on January 21, 2020
Runtime version: 11.0.5+10-b520.30 amd64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Linux 5.0.0-37-generic
GC: ParNew, ConcurrentMarkSweep
Memory: 725M
Cores: 4
Registry:
Non-Bundled Plugins: gherkin, cucumber-java
pom.xml
http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
<groupId>org.example</groupId>
<artifactId>RestAssured</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
UTF-8
7
io.cucumber
cucumber-java
4.8.0
<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-junit -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>4.8.0</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/io.rest-assured/rest-assured -->
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>4.1.2</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
-->
com.fasterxml.jackson.core
jackson-databind
2.10.1
this is the test runner class
package RestAssuredFramework.cucumber.Options;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
#RunWith(Cucumber.class)
#CucumberOptions(
features = "src/test/java/RestAssuredFramework",
glue = {"StepDefinition"}
)
public class TestRunner {
}
I also have the following plugins installed in intellij
Cucumber for java 193.5662.7
Gherkin 193.6015.53
You need to provide correct glue in #CucumberOptions annotation
glue = {"RestAssuredFramework.stepDefinitions"}
glue - is the package name where step definitions stored
I have an Apache Apex application DAG which reads RabbitMQ message from a queue. Which Apache Apex Malhar operator should I use? There are several operators but it's not clear which one to use and how to use it.
Have you looked at https://github.com/apache/apex-malhar/tree/master/contrib/src/main/java/com/datatorrent/contrib/rabbitmq ? There are also tests in https://github.com/apache/apex-malhar/tree/master/contrib/src/test/java/com/datatorrent/contrib/rabbitmq that show how to use the operator
https://github.com/apache/apex-malhar/blob/master/contrib/src/main/java/com/datatorrent/contrib/rabbitmq/AbstractRabbitMQInputOperator.java
That is the main operator code where the tuple type is a generic parameter and emitTuple() is an abstract method that subclasses need to implement.
AbstractSinglePortRabbitMQInputOperator is a simple subclass that provides a single output port and implements emitTuple() using another abstract method getTuple() which needs an implementation in its subclasses.
The tests that Sanjay pointed to show how to use these classes.
I also had problems finding out how to read messages from RabbitMQ to Apache Apex. With the help of the provided links of Sanjay's answer (https://stackoverflow.com/a/42210636/2350644) I finally managed to get it running. Here's how it works all together:
1. Setup a RabbitMQ Server
There are lot of ways installing RabbitMQ that are described here: https://www.rabbitmq.com/download.html
The simplest way for me was using docker (See: https://store.docker.com/images/rabbitmq)
docker pull rabbitmq
docker run -d --hostname my-rabbit --name some-rabbit -p 5672:5672 -p 15672:15672 rabbitmq:3-management
To check if RabbitMQ is working, open a browser and navigate to: http://localhost:15672/. You should see the Management page of RabbitMQ.
2. Write a Producer program
To send messages to the queue you can write a simple JAVA program like this:
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.util.ArrayList;
public class Send {
private final static String EXCHANGE = "myExchange";
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE, BuiltinExchangeType.FANOUT);
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName, EXCHANGE, "");
List<String> messages = Arrays.asList("Hello", "World", "!");
for (String msg : messages) {
channel.basicPublish(EXCHANGE, "", null, msg.getBytes("UTF-8"));
System.out.println(" [x] Sent '" + msg + "'");
}
channel.close();
connection.close();
}
}
If you execute the JAVA program you should see some outputs in the Management UI of RabbitMQ.
3. Implement a sample Apex Application
3.1 Bootstrap a sample apex application
Follow the official apex documentation http://docs.datatorrent.com/beginner/
3.2 Add additional dependencies to pom.xml
To use the classes provided by malhar add the following dependencies:
<dependency>
<groupId>org.apache.apex</groupId>
<artifactId>malhar-contrib</artifactId>
<version>3.7.0</version>
</dependency>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>4.2.0</version>
</dependency>
3.3 Create a Consumer
We first need to create an InputOperator that consumes messages from RabbitMQ using available code from apex-malhar.
import com.datatorrent.contrib.rabbitmq.AbstractSinglePortRabbitMQInputOperator;
public class MyRabbitMQInputOperator extends AbstractSinglePortRabbitMQInputOperator<String> {
#Override
public String getTuple(byte[] message) {
return new String(message);
}
}
You only have to override the getTuple() method. In this case we simply return the message that was received from RabbitMQ.
3.4 Setup an Apex DAG
To test the application we simply add an InputOperator (MyRabbitMQInputOperator that we implemented before) that consumes data from RabbitMQ and a ConsoleOutputOperator that prints the received messages.
import com.rabbitmq.client.BuiltinExchangeType;
import org.apache.hadoop.conf.Configuration;
import com.datatorrent.api.annotation.ApplicationAnnotation;
import com.datatorrent.api.StreamingApplication;
import com.datatorrent.api.DAG;
import com.datatorrent.api.DAG.Locality;
import com.datatorrent.lib.io.ConsoleOutputOperator;
#ApplicationAnnotation(name="MyFirstApplication")
public class Application implements StreamingApplication
{
private final static String EXCHANGE = "myExchange";
#Override
public void populateDAG(DAG dag, Configuration conf)
{
MyRabbitMQInputOperator consumer = dag.addOperator("Consumer", new MyRabbitMQInputOperator());
consumer.setHost("localhost");
consumer.setExchange(EXCHANGE);
consumer.setExchangeType(BuiltinExchangeType.FANOUT.getType());
ConsoleOutputOperator cons = dag.addOperator("console", new ConsoleOutputOperator());
dag.addStream("myStream", consumer.outputPort, cons.input).setLocality(Locality.CONTAINER_LOCAL);
}
}
3.5 Test the Application
To simply test the created application we can write a UnitTest, so there is no need to setup a Hadoop/YARN cluster.
In the bootstrap application there is already a UnitTest namely ApplicationTest.java that we can use:
import java.io.IOException;
import javax.validation.ConstraintViolationException;
import org.junit.Assert;
import org.apache.hadoop.conf.Configuration;
import org.junit.Test;
import com.datatorrent.api.LocalMode;
/**
* Test the DAG declaration in local mode.
*/
public class ApplicationTest {
#Test
public void testApplication() throws IOException, Exception {
try {
LocalMode lma = LocalMode.newInstance();
Configuration conf = new Configuration(true);
//conf.addResource(this.getClass().getResourceAsStream("/META-INF/properties.xml"));
lma.prepareDAG(new Application(), conf);
LocalMode.Controller lc = lma.getController();
lc.run(10000); // runs for 10 seconds and quits
} catch (ConstraintViolationException e) {
Assert.fail("constraint violations: " + e.getConstraintViolations());
}
}
}
Since we don't need any properties for this application the only thing changed in this file is uncommenting the line:
conf.addResource(this.getClass().getResourceAsStream("/META-INF/properties.xml"));
If you execute the ApplicationTest.java and send messages to RabbitMQ using the Producer program as described in 2., the Test should output all the messages.
You might need to increase the time of the test to see all messages (It is set to 10sec currently).
I'm new to JAX-RS and trying to figure out what is happening here:
I have a simple Hello World Jersey REST service running on Glassfish (Eclipse plugin). I can access it successfully from a browser.
Now, I'd like to call it from a Java class (so I can build JUnit tests around it) but I get this error on buildGet() method:
java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
Unless some magic I'm not aware of happens, I'm not packaging my service and/or client in any jar so it's not related to my application jar signature.
Anyone could explain what I'm doing wrong?
Why is the exception triggered on buildGet() metod and not on any method called before?
My main:
package com.test;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
public class HelloTest {
public static void main(String[] args)
{
Client client = ClientBuilder.newClient();
Response response = null;
try {
WebTarget webTarget = client.target("http://localhost:9595/Hello/api/ping");
Invocation helloInvocation = webTarget.request().buildGet();
response = helloInvocation.invoke();
}
catch (Throwable ex) {
System.out.println(ex.getMessage());
}
finally {
response.close();
}
}
}
My service:
package com.api;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("ping")
public class Hello
{
#GET
#Produces(MediaType.TEXT_HTML)
public String sayHtmlHello()
{
return "<html>" + "<title>" + "Hello" + "</title>"
+ "<body><h1>" + "Hello!!!" + "</body></h1>" + "</html>";
}
}
After struggling on this for a while, it seems that my Maven configuration had issues and some dependencies were not downloaded/built correctly. I restarted a new project, copied my source files and everything started to work as expected.
I have exposed an api provided by a jetty server to a front-end application. I want to make sure that only the front-end application (from a certain domain) has access to that api - any other requests should be unauthorised.
What's the best best way of implementing this security feature?
Update: I have set up a CrossOriginFilter - however, I can still access the api via basic GET request from my browser.
Thanks!
Use the IPAccessHandler to setup whitelists and blacklists.
Example: this will allow 127.0.0.* and 192.168.1.* to access everything.
But 192.168.1.132 cannot access /home/* content.
package jetty.demo;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.IPAccessHandler;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
public class IpAccessExample
{
public static void main(String[] args)
{
System.setProperty("org.eclipse.jetty.servlet.LEVEL","DEBUG");
System.setProperty("org.eclipse.jetty.server.handler.LEVEL","DEBUG");
Server server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(8080);
server.addConnector(connector);
// Setup IPAccessHandler
IPAccessHandler ipaccess = new IPAccessHandler();
ipaccess.addWhite("127.0.0.0-255|/*");
ipaccess.addWhite("192.168.1.1-255|/*");
ipaccess.addBlack("192.168.1.132|/home/*");
server.setHandler(ipaccess);
// Setup the basic application "context" for this application at "/"
// This is also known as the handler tree (in jetty speak)
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
// make context a subordinate of ipaccess
ipaccess.setHandler(context);
// The filesystem paths we will map
String homePath = System.getProperty("user.home");
String pwdPath = System.getProperty("user.dir");
// Fist, add special pathspec of "/home/" content mapped to the homePath
ServletHolder holderHome = new ServletHolder("static-home", DefaultServlet.class);
holderHome.setInitParameter("resourceBase",homePath);
holderHome.setInitParameter("dirAllowed","true");
holderHome.setInitParameter("pathInfoOnly","true");
context.addServlet(holderHome,"/home/*");
// Lastly, the default servlet for root content
// It is important that this is last.
ServletHolder holderPwd = new ServletHolder("default", DefaultServlet.class);
holderPwd.setInitParameter("resourceBase",pwdPath);
holderPwd.setInitParameter("dirAllowed","true");
context.addServlet(holderPwd,"/");
try
{
server.start();
server.join();
}
catch (Throwable t)
{
t.printStackTrace(System.err);
}
}
}
Or alternatively, write your own Handler to filter based on some other arbitrary rule.
Such as looking for a required request header, something that your specific front-end application provides, but a browser would not.
package jetty.demo;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.HandlerWrapper;
public class BanBrowserHandler extends HandlerWrapper
{
#Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
String xfe = request.getHeader("X-FrontEnd");
if ((xfe == null) || (!xfe.startsWith("MagicApp-")))
{
// not your front-end
response.sendError(HttpStatus.FORBIDDEN_403);
baseRequest.setHandled(true);
return;
}
getHandler().handle(target,baseRequest,request,response);
}
}
The class IPAccessHandler is deprecated. The InetAccessHandler is recommended.
org.eclipse.jetty.server.Server server = ...;
InetAccessHandler ipaccess = new InetAccessHandler();
ipaccess.include(clientIP);
ipaccess.setHandler(server.getHandler());
server.setHandler(ipaccess);