WatchService loop running twice unless stepping through in debug mode - watchservice

I am really new to WatchService and I am having a very interesting bug. When I run my code in normal mode(Run) it will loop through the for(Watch event: key1.pollEvents()) loop twice and create two google calander events but if I step through it using debug mode it only adds one event. I grabbed almost all of the code from online in an attempt to learn about how WatchService works. I don't really know what I am doing here so any help would be great. Here is my code
/*
* Copyright (c) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.api.services.samples.calendar.cmdline;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
import static java.nio.file.StandardWatchEventKinds.OVERFLOW;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.java6.auth.oauth2.FileCredentialStore;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.DateTime;
import com.google.api.client.util.Lists;
import com.google.api.services.calendar.CalendarScopes;
import com.google.api.services.calendar.model.Calendar;
import com.google.api.services.calendar.model.Event;
import com.google.api.services.calendar.model.Event.Reminders;
import com.google.api.services.calendar.model.EventDateTime;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Scanner;
import java.util.TimeZone;
/**
* #author Yaniv Inbar
*/
public class myCalendar {
/**
* Be sure to specify the name of your application. If the application name is {#code null} or
* blank, the application will log a warning. Suggested format is "MyCompany-ProductName/1.0".
*/
private static final String APPLICATION_NAME = "";
/** Global instance of the HTTP transport. */
private static HttpTransport HTTP_TRANSPORT;
/** Global instance of the JSON factory. */
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
private static com.google.api.services.calendar.Calendar client;
static final java.util.List<Calendar> addedCalendarsUsingBatch = Lists.newArrayList();
/** Authorizes the installed application to access user's protected data. */
private static Credential authorize() throws Exception {
// load client secrets
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY,
new InputStreamReader(myCalendar.class.getResourceAsStream("/client_secrets.json")));
if (clientSecrets.getDetails().getClientId().startsWith("Enter")
|| clientSecrets.getDetails().getClientSecret().startsWith("Enter ")) {
System.out.println(
"Enter Client ID and Secret from https://code.google.com/apis/console/?api=calendar "
+ "into calendar-cmdline-sample/src/main/resources/client_secrets.json");
System.exit(1);
}
// set up file credential store
FileCredentialStore credentialStore = new FileCredentialStore(
new File(System.getProperty("user.home"), ".credentials/calendar.json"), JSON_FACTORY);
// set up authorization code flow
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
HTTP_TRANSPORT, JSON_FACTORY, clientSecrets,
Collections.singleton(CalendarScopes.CALENDAR)).setCredentialStore(credentialStore).build();
// authorize
return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
}
public static void main(String[] args) throws IOException {
Path dir = Paths.get("C:\\Users\\kdevocht\\Dropbox\\Apps\\Attachments\\kjdevocht#gmail.com\\");
WatchService service = FileSystems.getDefault().newWatchService();
WatchKey key = dir.register(service, ENTRY_MODIFY);
System.out.println("Watching directory: "+dir.toString());
for(;;){
WatchKey key1;
try {
key1 = service.take();
} catch (InterruptedException x) {
break;
}
for (WatchEvent<?> event: key1.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
if (kind == OVERFLOW) {
continue;
}
WatchEvent<Path> ev = (WatchEvent<Path>)event;
Path filename = ev.context();
Path child = dir.resolve(filename);
System.out.println("File: "+child.toString()+" modified.");
try{
try {
try {
// initialize the transport
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
// authorization
Credential credential = authorize();
// set up global Calendar instance
client = new com.google.api.services.calendar.Calendar.Builder(
HTTP_TRANSPORT, JSON_FACTORY, credential).setApplicationName(
APPLICATION_NAME).build();
// run commands
Calendar calendar = client.calendars().get("kjdevocht#gmail.com").execute();
addEvent(calendar, child.toString());
} catch (IOException e) {
System.err.println(e.getMessage());
}
} catch (Throwable t) {
t.printStackTrace();
}
//System.exit(1);;
}catch(Exception x){
x.printStackTrace();
}
}
boolean valid = key.reset();
if (!valid) {
break;
}
/* try {
Thread.sleep(5000);
} catch(InterruptedException e) {
} */
}
I thought it might have been a timing issue so I tried a sleep try catch but that did not work.

So it seems everything was working fine. I was using notepad++ to edit a file in the dir I was watching. After some research it appears that two modifications are made and so two events are logged. Some people have suggested storing the time stamp of the file and only react when it changes, this seems to filter out the multiple events. For me and what I was doing, I just changed to watching for a create event. This works great now with no problems

Related

Put event in Amazaon Event bus using Jmeter

We are introducing an event bridge to communicate btw 2 components and we want to Performance test the inbound event bus.
We are using jmeter and want to to do a put event in this inbound event bus. has anyone done something like this ?
Probably the most straightforward way is using AWS SDK for Java from JSR223 Test Elements with Groovy
Example code can be found at Working with Amazon EventBridge, I'll add it here just in case
/*
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package com.example.eventbridge;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.eventbridge.EventBridgeClient;
import software.amazon.awssdk.services.eventbridge.model.EventBridgeException;
import software.amazon.awssdk.services.eventbridge.model.PutEventsRequest;
import software.amazon.awssdk.services.eventbridge.model.PutEventsRequestEntry;
import software.amazon.awssdk.services.eventbridge.model.PutEventsResponse;
import software.amazon.awssdk.services.eventbridge.model.PutEventsResultEntry;
import java.util.ArrayList;
import java.util.List;
/**
* To run this Java V2 code example, ensure that you have setup your development environment, including your credentials.
*
* For information, see this documentation topic:
*
* https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
*/
public class PutEvents {
public static void main(String[] args) {
final String USAGE =
"To run this example, supply two resources, identified by Amazon Resource Name (ARN), which the event primarily concerns. " +
"Any number, including zero, may be present. \n" +
"For example: PutEvents <resourceArn> <resourceArn2>\n";
if (args.length != 2) {
System.out.println(USAGE);
System.exit(1);
}
String resourceArn = args[0];
String resourceArn2 = args[1];
Region region = Region.US_WEST_2;
EventBridgeClient eventBrClient = EventBridgeClient.builder()
.region(region)
.build();
putEBEvents(eventBrClient, resourceArn, resourceArn2);
eventBrClient.close();
}
public static void putEBEvents(EventBridgeClient eventBrClient, String resourceArn, String resourceArn2 ) {
try {
// Populate a List with the resource ARN values
List<String> resources = new ArrayList<String>();
resources.add(resourceArn);
resources.add(resourceArn2);
PutEventsRequestEntry reqEntry = PutEventsRequestEntry.builder()
.resources(resources)
.source("com.mycompany.myapp")
.detailType("myDetailType")
.detail("{ \"key1\": \"value1\", \"key2\": \"value2\" }")
.build();
// Add the PutEventsRequestEntry to a list
List<PutEventsRequestEntry> list = new ArrayList<PutEventsRequestEntry>();
list.add(reqEntry);
PutEventsRequest eventsRequest = PutEventsRequest.builder()
.entries(reqEntry)
.build();
PutEventsResponse result = eventBrClient.putEvents(eventsRequest);
for (PutEventsResultEntry resultEntry : result.entries()) {
if (resultEntry.eventId() != null) {
System.out.println("Event Id: " + resultEntry.eventId());
} else {
System.out.println("Injection failed with Error Code: " + resultEntry.errorCode());
}
}
} catch (EventBridgeException e) {
System.err.println(e.awsErrorDetails().errorMessage());
System.exit(1);
}
}
}
Was able to do it by using the os process sampler and using the AWS cli commands.

checking database from webservice netbeans

sorry if my question confusing cause this is the first time i make a question. if there is something that i can do to make it clearer, just tell me so i can improve the way i'm asking.
currently i'm trying to make web service from netbeans that can check some data from database. Because i'm newbie so i followed tutorial from
http://programmerguru.com/webservice-tutorial/how-to-create-java-webservice-in-netbeans/ to make the web service.
but when i trying to check the database with my usual way with mybattis, it keep in give me java.lang.nulpointerexception. when i try to debug it, it give me "variable information not available, source compiled without -g option" and throw me to InvocationTargetException.java
public InvocationTargetException(Throwable target) {
super((Throwable)null); // Disallow initCause
this.target = target;
}
here is the code for the web service
/*
* To change this license header, choose License Headers in Project
Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.bismillah.berkah;
import com.bismillah.berkah.dao.DummyDao;
import com.bismillah.berkah.daoImpl.DummyDaoImpl;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.WebParam;
/**
*
* #author Ari
*/
#WebService(serviceName = "Check4Update")
public class Check4Update {
public DummyDaoImpl ddi;
/**
* This is a sample web service operation
*
* #param InTerminalNumber
* #return
*/
#WebMethod(operationName = "CheckUpdate")
public String hello(#WebParam(name = "InTerminalNumber") String InTerminalNumber) {
String OutError = "";
String OutMessage = "";
if (InTerminalNumber == null) {
return "InTerminalNumber can't be null";
} else {
Map mapdao = new HashMap<String, Object>();
Map map = new HashMap<String, Object>();
map.put("InTerminalNumber", InTerminalNumber);
mapdao = ddi.check4UpdatePatch(map);
OutError = (String) mapdao.get("OutError");
OutMessage = (String) mapdao.get("OutMessage");
return "Error : " + OutError + ", with message : " + OutMessage;
}
}
public void setDdi(DummyDaoImpl ddi) {
this.ddi = ddi;
}
}
and here is the code mybattis impl
package com.bismillah.berkah.daoImpl;
import com.bismillah.berkah.Check4Update;
import com.bismillah.berkah.config.MyBatisConnectionFactory;
import com.bismillah.berkah.dao.*;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
/**
*
* #author Ari
*/
public class DummyDaoImpl
{
private SqlSessionFactory sqlSessionFactory;
public DummyDaoImpl()
{
sqlSessionFactory = MyBatisConnectionFactory.getSqlSessionFactory();
}
public Map check4UpdatePatch(Map map)
{
Check4Update c4u = new Check4Update();
c4u.setDdi(this);
SqlSession session = sqlSessionFactory.openSession();
try
{
session.selectOne("dummy.check4UpdatePatch", map);
} catch (Exception ex)
{
ex.toString();
} finally
{
session.close();
}
return map;
}
}
could you tell me how to fix it? so i can get the data? by the way i always get thrown at my web service, here exactly
mapdao = ddi.check4UpdatePatch(map);
once again sorry if my question confusing cause this is the first time i make a question. if there is something that i can do to make it clearer, just tell me so i can improve the way i'm asking.
sorry already found the problem, it is cause wrong configuration on mybatis.
i haven't change my string resource on MyBatisConnectionFactory, also the one at xml file.
maybe that's why i always get java lang nul.
actually when i trying to fix this, i make some interface class too, but still not working until i find my problem. if anyone have some problem like me maybe you can fix it with adding some interface so the impl will override the interface.

Unable to use http connector

I'm trying to use the http connector that is provided with the standard Camunda implementation with no luck. Every single time that I run my workflow the instance simply freeze on that activity. I'm using this class in an execution listnener and the code that I'm using is this:
import org.apache.ibatis.logging.LogFactory;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.Expression;
import org.camunda.bpm.engine.delegate.JavaDelegate;
import org.camunda.bpm.engine.impl.util.json.JSONObject;
import org.camunda.connect.Connectors;
import org.camunda.connect.ConnectorException;
import org.camunda.connect.httpclient.HttpConnector;
import org.camunda.connect.httpclient.HttpResponse;
import org.camunda.connect.httpclient.impl.HttpConnectorImpl;
import org.camunda.connect.impl.DebugRequestInterceptor;
public class APIAudit implements JavaDelegate {
static {
LogFactory.useSlf4jLogging(); // MyBatis
}
private static final java.util.logging.Logger LOGGER = java.util.logging.Logger.getLogger(Thread.currentThread().getStackTrace()[0].getClassName());
private Expression tokenField;
private Expression apiServerField;
private Expression questionIDField;
private Expression subjectField;
private Expression bodyField;
public void execute(DelegateExecution arg0) throws Exception {
String tokenValue = (String) tokenField.getValue(arg0);
String apiServerValue = (String) apiServerField.getValue(arg0);
String questionIDValue = (String) questionIDField.getValue(arg0);
String subjectValue = (String) subjectField.getValue(arg0);
String bodyValue = (String) bodyField.getValue(arg0);
if (apiServerValue != null) {
String url = "http://" + apiServerValue + "/v1.0/announcement";
LOGGER.info("token: " + tokenValue);
LOGGER.info("apiServer: " + apiServerValue);
LOGGER.info("questionID: " + questionIDValue);
LOGGER.info("subject: " + subjectValue);
LOGGER.info("body: " + bodyValue);
LOGGER.info("url: " + url);
JSONObject jsonBody = new JSONObject();
jsonBody.put("access_token", tokenValue);
jsonBody.put("source", "SYSTEM");
jsonBody.put("target", "AUDIT");
jsonBody.put("tType", "system");
jsonBody.put("aType", "auditLog");
jsonBody.put("affectedItem", questionIDValue);
jsonBody.put("subject", subjectValue);
jsonBody.put("body", bodyValue);
jsonBody.put("language", "EN");
try {
LOGGER.info("Generating connection");
HttpConnector http = Connectors.getConnector(HttpConnector.ID);
LOGGER.info(http.toString());
DebugRequestInterceptor interceptor = new DebugRequestInterceptor(false);
http.addRequestInterceptor(interceptor);
LOGGER.info("JSON Body: " + jsonBody.toString());
HttpResponse response = http.createRequest()
.post()
.url(url)
.contentType("application/json")
.payload(jsonBody.toString())
.execute();
Integer responseCode = response.getStatusCode();
String responseBody = response.getResponse();
response.close();
LOGGER.info("[" + responseCode + "]: " + responseBody);
} catch (ConnectorException e) {
LOGGER.severe(e.getMessage());
}
} else {
LOGGER.info("No APISERVER provided");
}
LOGGER.info("Exiting");
}
}
I'm sure that the fields injection works correctly since the class prints the correct values. I also used the http-connector in javascript in the same activity with no problem.
I'm using this approach since I need to make two different calls to external REST services in the same task, so any advice will be very welcome.
You need to enable Connect process engine plugin in process engine configuration. Not sure how you configured the process engine, make sure to add this plugin org.camunda.connect.plugin.impl.ConnectProcessEnginePlugin
Also check the following in dependencies
Do not add both dependencies - connectors-all and http-connector.
Make sure to check the error logs and see whether you have any class loading problem related to httpclient classes
I am pretty sure there is a class loading issue with http client library. make sure to include the correct version of connectors-all dependency

How to unit test grpc-java server implementation functions?

I have an implementation of GRPC-java server code, but I didn't find the example code to unit test the StreamObserver. Does anyone know the right way to unit test the function?
public class RpcTrackDataServiceImpl implements TrackDataServiceGrpc.TrackDataService {
#Override
public void getTracks(GetTracksRequest request, StreamObserver < GetTracksResponse > responseObserver) {
GetTracksResponse reply = GetTracksResponse
.newBuilder()
.addTracks(TrackInfo.newBuilder()
.setOwner("test")
.setTrackName("test")
.build())
.build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
Unit testing is very straight forward using the InProcess transport mentioned by Eric above. Here is an example a bit more explicit on code:
We test a service based on this protobuff definition:
syntax = "proto3";
option java_multiple_files = true;
option java_package = "servers.dummy";
option java_outer_classname = "DummyProto";
option objc_class_prefix = "DMYS";
package dummy;
import "general.proto";
// The dummy service definition.
service DummyService {
// # Misc
// Returns the server version
rpc getVersion (Empty) returns (ServerVersion) {}
// Returns the java version
rpc getJava (Empty) returns (JavaVersion) {}
}
// Transmission data types
(The following file is included above:)
syntax = "proto3";
option java_multiple_files = true;
option java_package = "general";
option java_outer_classname = "General";
option objc_class_prefix = "G";
// Transmission data types
message Empty {} // Empty Request or Reply
message ServerVersion {
string version = 1;
}
message JavaVersion {
string version = 1;
}
The DummyService based on the generated Java from the Protoc compiler is the following:
package servers.dummy;
import java.util.logging.Logger;
import general.Empty;
import general.JavaVersion;
import general.ServerVersion;
import io.grpc.stub.StreamObserver;
public class DummyService extends DummyServiceGrpc.DummyServiceImplBase {
private static final Logger logger = Logger.getLogger(DummyService.class.getName());
#Override
public void getVersion(Empty req, StreamObserver<ServerVersion> responseObserver) {
logger.info("Server Version-Request received...");
ServerVersion version = ServerVersion.newBuilder().setVersion("1.0.0").build();
responseObserver.onNext(version);
responseObserver.onCompleted();
}
#Override
public void getJava(Empty req, StreamObserver<JavaVersion> responseObserver) {
logger.info("Java Version Request received...");
JavaVersion version = JavaVersion.newBuilder().setVersion(Runtime.class.getPackage().getImplementationVersion() + " (" + Runtime.class.getPackage().getImplementationVendor() + ")").build();
responseObserver.onNext(version);
responseObserver.onCompleted();
}
}
Now we build an InProcessServer that runs our Dummy service (or any other service you want to test):
package servers;
import io.grpc.Server;
import io.grpc.inprocess.InProcessServerBuilder;
import java.io.IOException;
import java.util.logging.Logger;
import servers.util.PortServer;
/**
* InProcessServer that manages startup/shutdown of a service within the same process as the client is running. Used for unit testing purposes.
* #author be
*/
public class InProcessServer<T extends io.grpc.BindableService> {
private static final Logger logger = Logger.getLogger(PortServer.class.getName());
private Server server;
private Class<T> clazz;
public InProcessServer(Class<T> clazz){
this.clazz = clazz;
}
public void start() throws IOException, InstantiationException, IllegalAccessException {
server = InProcessServerBuilder
.forName("test")
.directExecutor()
.addService(clazz.newInstance())
.build()
.start();
logger.info("InProcessServer started.");
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
// Use stderr here since the logger may have been reset by its JVM shutdown hook.
System.err.println("*** shutting down gRPC server since JVM is shutting down");
InProcessServer.this.stop();
System.err.println("*** server shut down");
}
});
}
void stop() {
if (server != null) {
server.shutdown();
}
}
/**
* Await termination on the main thread since the grpc library uses daemon threads.
*/
public void blockUntilShutdown() throws InterruptedException {
if (server != null) {
server.awaitTermination();
}
}
}
We can now test the service using the following unit test:
package servers;
import static org.junit.Assert.*;
import general.ServerVersion;
import io.grpc.ManagedChannel;
import io.grpc.StatusRuntimeException;
import io.grpc.inprocess.InProcessChannelBuilder;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import servers.dummy.DummyService;
import servers.dummy.DummyServiceGrpc;
import servers.dummy.DummyServiceGrpc.DummyServiceBlockingStub;
import servers.dummy.DummyServiceGrpc.DummyServiceStub;
public class InProcessServerTest {
private static final Logger logger = Logger.getLogger(InProcessServerTest.class.getName());
private InProcessServer<DummyService> inprocessServer;
private ManagedChannel channel;
private DummyServiceBlockingStub blockingStub;
private DummyServiceStub asyncStub;
public InProcessServerTest() {
super();
}
#Test
public void testInProcessServer() throws InterruptedException{
try {
String version = getServerVersion();
assertEquals("1.0.0", version);
} finally {
shutdown();
}
}
/** Ask for the server version */
public String getServerVersion() {
logger.info("Will try to get server version...");
ServerVersion response;
try {
response = blockingStub.getVersion(null);
} catch (StatusRuntimeException e) {
logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
fail();
return "";
}
return response.getVersion();
}
#Before
public void beforeEachTest() throws InstantiationException, IllegalAccessException, IOException {
inprocessServer = new InProcessServer<DummyService>(DummyService.class);
inprocessServer.start();
channel = InProcessChannelBuilder
.forName("test")
.directExecutor()
// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
// needing certificates.
.usePlaintext(true)
.build();
blockingStub = DummyServiceGrpc.newBlockingStub(channel);
asyncStub = DummyServiceGrpc.newStub(channel);
}
#After
public void afterEachTest(){
channel.shutdownNow();
inprocessServer.stop();
}
public void shutdown() throws InterruptedException {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
}
}
The test does only test one of two methods, as it is just for illustration purposes. The other method can be tested accordingly.
See the RouteGuideExample for more information on how to test both server and client:
https://github.com/grpc/grpc-java/blob/master/examples/src/test/java/io/grpc/examples/routeguide/RouteGuideServerTest.java
I'd suggest using the InProcess transport. The InProcess transport is very lightweight but also is using much of the "real" code, so the behavior closely matches a real transport. If you also use directExecutor() for the Channel and Server then the test is essentially single-threaded and will be deterministic. (Although another thread would still be used for deadline handling.)
Although the question is for unit testing a service, InProcess is also great for unit testing a client.
I ended up with a solution to create a FakeStreamObserver that implements the StreamObserver interface.
The FakeStreamObserver is passed in to execute onNext, onCompleted etc.
I'm not sure if this is the best way or not.
I will insert snippets from the official gRPC examples. I have successfully created tests based on these HelloWorld example.
The HelloWorldService:
/*
* Copyright 2015, gRPC Authors All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.grpc.examples.helloworld;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;
import java.io.IOException;
import java.util.logging.Logger;
/**
* Server that manages startup/shutdown of a {#code Greeter} server.
*/
public class HelloWorldServer {
private static final Logger logger = Logger.getLogger(HelloWorldServer.class.getName());
private Server server;
private void start() throws IOException {
/* The port on which the server should run */
int port = 50051;
server = ServerBuilder.forPort(port)
.addService(new GreeterImpl())
.build()
.start();
logger.info("Server started, listening on " + port);
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
// Use stderr here since the logger may have been reset by its JVM shutdown hook.
System.err.println("*** shutting down gRPC server since JVM is shutting down");
HelloWorldServer.this.stop();
System.err.println("*** server shut down");
}
});
}
private void stop() {
if (server != null) {
server.shutdown();
}
}
/**
* Await termination on the main thread since the grpc library uses daemon threads.
*/
private void blockUntilShutdown() throws InterruptedException {
if (server != null) {
server.awaitTermination();
}
}
/**
* Main launches the server from the command line.
*/
public static void main(String[] args) throws IOException, InterruptedException {
final HelloWorldServer server = new HelloWorldServer();
server.start();
server.blockUntilShutdown();
}
static class GreeterImpl extends GreeterGrpc.GreeterImplBase {
#Override
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
}
And the test:
/*
* Copyright 2016, gRPC Authors All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.grpc.examples.helloworld;
import static org.junit.Assert.assertEquals;
import io.grpc.examples.helloworld.HelloWorldServer.GreeterImpl;
import io.grpc.testing.GrpcServerRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
* Unit tests for {#link HelloWorldServer}.
* For demonstrating how to write gRPC unit test only.
* Not intended to provide a high code coverage or to test every major usecase.
*
* <p>For more unit test examples see {#link io.grpc.examples.routeguide.RouteGuideClientTest} and
* {#link io.grpc.examples.routeguide.RouteGuideServerTest}.
*/
#RunWith(JUnit4.class)
public class HelloWorldServerTest {
/**
* This creates and starts an in-process server, and creates a client with an in-process channel.
* When the test is done, it also shuts down the in-process client and server.
*/
#Rule
public final GrpcServerRule grpcServerRule = new GrpcServerRule().directExecutor();
/**
* To test the server, make calls with a real stub using the in-process channel, and verify
* behaviors or state changes from the client side.
*/
#Test
public void greeterImpl_replyMessage() throws Exception {
// Add the service to the in-process server.
grpcServerRule.getServiceRegistry().addService(new GreeterImpl());
GreeterGrpc.GreeterBlockingStub blockingStub =
GreeterGrpc.newBlockingStub(grpcServerRule.getChannel());
String testName = "test name";
HelloReply reply = blockingStub.sayHello(HelloRequest.newBuilder().setName(testName).build());
assertEquals("Hello " + testName, reply.getMessage());
}
}
You can fin other examples, if you clone the examples repository as they describe it here:
https://grpc.io/docs/tutorials/basic/java.html
I hope it will help you, too.
Br,
Renato
#RunWith(JUnit4.class)
public class HelloWorldServerTest {
/**
* This rule manages automatic graceful shutdown for the registered servers and channels at the
* end of test.
*/
#Rule
public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule();
/**
* To test the server, make calls with a real stub using the in-process channel, and verify
* behaviors or state changes from the client side.
*/
#Test
public void greeterImpl_replyMessage() throws Exception {
// Generate a unique in-process server name.
String serverName = InProcessServerBuilder.generateName();
// Create a server, add service, start, and register for automatic graceful shutdown.
grpcCleanup.register(InProcessServerBuilder
.forName(serverName).directExecutor().addService(new GreeterImpl()).build().start());
GreeterGrpc.GreeterBlockingStub blockingStub = GreeterGrpc.newBlockingStub(
// Create a client channel and register for automatic graceful shutdown.
grpcCleanup.register(InProcessChannelBuilder.forName(serverName).directExecutor().build()));
HelloReply reply =
blockingStub.sayHello(HelloRequest.newBuilder().setName( "test name").build());
assertEquals("Hello test name", reply.getMessage());
}
}
https://github.com/grpc/grpc-java/blob/master/examples/src/test/java/io/grpc/examples/helloworld/HelloWorldServerTest.java
First, refactor the code so it's easier to unit test:
public class RpcTrackDataServiceImpl implements TrackDataServiceGrpc.TrackDataService {
#Override
public void getTracks(GetTracksRequest request, StreamObserver<GetTracksResponse> responseObserver) {
GetTracksResponse reply = getTracks(request);
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
#VisibleForTesting
GetTracksResponse getTracks(GetTracksRequest request) {
return GetTracksResponse
.newBuilder()
.addTracks(TrackInfo.newBuilder()
.setOwner("test")
.setTrackName("test")
.build())
.build();
}
}
Small tests can then be written for each (more easily if using Spring Boot):
public class UnitTest {
private final ApplicationContextRunner applicationContextRunner = new ApplicationContextRunner();
#Configuration
public static class GetTracksConfiguration {
#Bean
public GetTracksService getTracksService() {
return new GetTracksService();
}
}
#Test
public void replyShouldBeSent() {
final GetTracksRequest request = GetTracksRequest.newBuilder().build();
final StreamObserver<GetTracksResponse> response = mock(StreamObserver.class);
applicationContextRunner
.withUserConfiguration(RequestTracksConfiguration.class)
.run(context -> {
assertThat(context)
.hasSingleBean(RequestTracksService.class);
context.getBean(RequestTracksService.class)
.getTracks(request, response);
verify(response, times(1)).onNext(any(GetTracksResponse.class));
verify(response, times(1)).onCompleted();
verify(response, never()).onError(any(Throwable.class));
});
}
#Test
public void shouldTestLogic {
assertLogicInFactoredOutMethodIsCorrect();
}
The larger test should then only test the startup and wiring:
#RunWith(SpringRunner.class)
#SpringBootTest(
classes = {GetTracksService.class}
)
#EnableAutoConfiguration
public class SmokeTest {
private GetTracksServiceGrpc.GetTracksServiceBlockingStub blockingStub;
#Test
public void springClientConnects() {
final GetTracksRequest request = GetTracksRequest.newBuilder()
.build();
assertNotNull(blockingStub.getTracks(request));
}
}
Note: The above code may not work OOTB since I've left out some annotations we use internally.
The major point is there's no need to pay for the cost of bringing up a server for unit tests that are meant to test logic.

openid4java ConsumerManager request/thread safe?

I am using openid4java in servlets. I have two servlets - one which performs first step (redirects user to login/accept application access) and second, which processes resulting information
In the documentation, there is written, that org.openid4java.consumer.ConsumerManager class must be the same instance in both steps. Can I create singleton for that? Is it thread and request safe?
Thanks for your replies!
In the consumer servlet from official openid4java sample it seems that ConsumerManager is thread safe - they use single ConsumerManager instance for all sessions. I use it this way too and have not noticed any strange behaviour yet. But a javadoc statement about thread-safety from the developers would be great...
//Currently only working with google only
// Try this - this is all ine one..
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
//import org.jboss.web.tomcat.security.login.WebAuthentication;
import org.openid4java.OpenIDException;
import org.openid4java.consumer.ConsumerException;
import org.openid4java.consumer.ConsumerManager;
import org.openid4java.consumer.VerificationResult;
import org.openid4java.discovery.DiscoveryInformation;
import org.openid4java.discovery.Identifier;
import org.openid4java.message.AuthRequest;
import org.openid4java.message.AuthSuccess;
import org.openid4java.message.ParameterList;
import org.openid4java.message.ax.AxMessage;
import org.openid4java.message.ax.FetchRequest;
import org.openid4java.message.ax.FetchResponse;
public class OpenAuth extends javax.servlet.http.HttpServlet {
final static String YAHOO_ENDPOINT = "https://me.yahoo.com";
final static String GOOGLE_ENDPOINT = "https://www.google.com/
accounts/o8/id";
//Updated version of example code from :
https://crisdev.wordpress.com/2011/03/23/openid4java-login-example/
//Add your servlet script path here - so if auth fails or
succeeds it will carry out actions - check below in doGet
public String scr="/servlets/MyServlet";
private ServletContext context;
private ConsumerManager manager;
private ConsumerManager mag;
//Code updated by Vahid Hedayati http://pro.org.uk
//Removed config init - moved post to doGet - since previous code
required it to be a post but also to include identifier as part of
url
//identifier was also the same variable used for Identifier code -
//cleaned up to make different variable and less confusion
//doGet identifer changed to openid_identifier and it also now looks
for openid_username which are the default variables returned from
openid-selector
//http://groups.google.com/group/openid4java/browse_thread/thread/
5e8f24f51f54dc2c
//After reading above post - store the manager in the session object
and failing with Yahoo authentication I changed code for the manager
//manage
public void doPost(HttpServletRequest req,HttpServletResponse
response) throws ServletException,IOException {
doGet(req, response);
}
protected void doGet(HttpServletRequest req, HttpServletResponse
resp) throws ServletException, IOException {
//New variable
String ouser=(String)req.getParameter("openid_username");
if (ouser==null) { ouser="";}
//Mage is the session value of openid_consumer_manager if it is
null it will generate it once
//And where ever manager is called within code it first returns
managers value by looking up session value
mag=(ConsumerManager)req.getSession().getAttribute("open_id_consumer_manager");
if (mag==null) {
this.manager = new ConsumerManager();
req.getSession().setAttribute("open_id_consumer_manager", manager);
}
String identify=(String)req.getParameter("openid_identifier");
if (identify==null) { identify="";}
if (!identify.equals("")) {
this.authRequest(identify,ouser, req, resp);
}else{
//If they have succeeded it will return them to welcome
//welcome looks up if NEWUSER = yes in the session value below
and if so
//scr now has the ip city/country/postcode so it finalises
user additiion by adding users ip country/city/ip as their sign up
// if not new well they are already logged in from the
relevant session values this code has put in so updats records and
returns they my accoount
//if authentication here failed or they rejected sharing their
email then login page is returned
Identifier identifier = this.verifyResponse(req);
if (identifier != null) {
resp.sendRedirect(scr+"?act=welcome");
} else {
resp.sendRedirect(scr+"?act=login");
}
}
}
// --- placing the authentication request ---
public String authRequest(String userSuppliedString,String Ouser,
HttpServletRequest httpReq, HttpServletResponse httpResp) throws
IOException {
try {
// configure the return_to URL where your application will
receive
// the authentication responses from the OpenID provider
String returnToUrl = httpReq.getRequestURL().toString();
// --- Forward proxy setup (only if needed) ---
// ProxyProperties proxyProps = new ProxyProperties();
// proxyProps.setProxyName("proxy.example.com");
// proxyProps.setProxyPort(8080);
// HttpClientFactory.setProxyProperties(proxyProps);
// perform discovery on the user-supplied identifier
//Modified - Look up manager value from session
manager = (ConsumerManager)
httpReq.getSession().getAttribute("open_id_consumer_manager");
List discoveries = manager.discover(userSuppliedString);
// attempt to associate with the OpenID provider
// and retrieve one service endpoint for authentication
DiscoveryInformation discovered =
manager.associate(discoveries);
// store the discovery information in the user's session
httpReq.getSession().setAttribute("openid-disc", discovered);
// obtain a AuthRequest message to be sent to the OpenID
provider
AuthRequest authReq = manager.authenticate(discovered,
returnToUrl);
FetchRequest fetch = FetchRequest.createFetchRequest();
if (userSuppliedString.startsWith(GOOGLE_ENDPOINT)) {
fetch.addAttribute("email", "http://axschema.org/
contact/email", true);
fetch.addAttribute("firstName", "http://axschema.org/
namePerson/first", true);
fetch.addAttribute("lastName", "http://axschema.org/
namePerson/last", true);
} else if (userSuppliedString.startsWith(YAHOO_ENDPOINT)) {
fetch.addAttribute("email", "http://axschema.org/
contact/email", true);
fetch.addAttribute("fullname", "http://axschema.org/
namePerson", true);
} else {
// works for myOpenID
fetch.addAttribute("fullname", "http://
schema.openid.net/namePerson", true);
fetch.addAttribute("email", "http://schema.openid.net/
contact/email", true);
}
httpReq.getSession().setAttribute("Ouser",Ouser);
// attach the extension to the authentication request
authReq.addExtension(fetch);
httpResp.sendRedirect(authReq.getDestinationUrl(true));
} catch (OpenIDException e) {
// present error to the user
}
return null;
}
// --- processing the authentication response ---
public Identifier verifyResponse(HttpServletRequest httpReq) {
try {
// extract the parameters from the authentication response
// (which comes in as a HTTP request from the OpenID provider)
ParameterList response = new
ParameterList(httpReq.getParameterMap());
// retrieve the previously stored discovery information
DiscoveryInformation discovered = (DiscoveryInformation)
httpReq.getSession().getAttribute("openid-disc");
// extract the receiving URL from the HTTP request
StringBuffer receivingURL = httpReq.getRequestURL();
String queryString = httpReq.getQueryString();
if (queryString != null && queryString.length() > 0)
receivingURL.append("?").append(httpReq.getQueryString());
// verify the response; ConsumerManager needs to be the same
// (static) instance used to place the authentication request
//Modified - look up session value before running verification
result
manager = (ConsumerManager)
httpReq.getSession().getAttribute("open_id_consumer_manager");
VerificationResult verification =
manager.verify(receivingURL.toString(), response, discovered);
// examine the verification result and extract the verified
// identifier
Identifier verified = verification.getVerifiedId();
String id=verified.getIdentifier();
if (verified != null) {
AuthSuccess authSuccess = (AuthSuccess)
verification.getAuthResponse();
if (authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) {
FetchResponse fetchResp = (FetchResponse)
authSuccess.getExtension(AxMessage.OPENID_NS_AX);
List emails =
fetchResp.getAttributeValues("email");
String email = (String) emails.get(0);
////////////////////////////////////////////////////////////////////////////////
//Custom bit each person needs to implement to
interact with their application:
//Authenticate the user, send email verify if
user exists on local system
//If it does {
//
httpReq.getSession().setAttribute("USERNAME",usern);
httpReq.getSession().setAttribute("LOGGEDIN", "on");
//}else{
String firstName =
fetchResp.getAttributeValue("firstName");
String lastName =
fetchResp.getAttributeValue("lastName");
String
fullname=fetchResp.getAttributeValue("fullname");
if (fullname==null)
{fullname="";}
if (firstName==null)
{ firstName="";}
if (lastName==null) { lastName="";}
if (!fullname.equals("")) {
if (fullname.indexOf(",")>-1)
{
firstName=fullname.substring(0,fullname.indexOf(","));
lastName=fullname.substring(fullname.indexOf(","),fullname.length());
}else if (fullname.indexOf("
")>-1){
firstName=fullname.substring(0,fullname.indexOf(" "));
lastName=fullname.substring(fullname.indexOf(" "),fullname.length());
}
}
//This is username returned
from the various services that ask for a username - it is returned as
openid_username
//When using openid-selector it uses
openid_identifier and openid_username - which is what this program now
looks for
String
ouser=(String)httpReq.getSession().getValue("Ouser");
if (ouser==null) {ouser="";}
//Adduser -- pass email address and
ouser
//In Adduser class - if ouser is blank
split email from 0 to substring.indexOf("#")
// generate a random number - look up
current user - if exist add random number to end
//and add user with email and new
username
//return bac the newuser and log in
like above.
httpReq.getSession().setAttribute("NEWUSER","YES");
//
httpReq.getSession().setAttribute("USERNAME",usern);
httpReq.getSession().setAttribute("LOGGEDIN", "on");
//}
return verified; // success
}
}
} catch (OpenIDException e) {
// present error to the user
}
return null;
}