I am trying to push message in firebase real time database through firebase admin sdk java, but my problem is that the same code works
fine on my local system and I am able to push message successfully
in database but its not working in testing environment and testing
environment is AWS server with ubuntu installed in
it, on researching it on google I am not able to find solution for
this?
public static class User {
public String date_of_birth;
public String full_name;
public String nickname;
public User(String date_of_birth, String full_name) {
// ...
}
public User(String date_of_birth, String full_name, String nickname) {
// ...
}
}
Map<String, User> users = new HashMap<>();
users.put("alanisawesome", new User("June 23, 1912", "Alan Turing"));
users.put("gracehop", new User("December 9, 1906", "Grace Hopper"));
Code for making connection is.....
FileInputStream serviceAccount;
FirebaseOptions options;
try {
serviceAccount = new FileInputStream("/********.json");
options = new FirebaseOptions.Builder()
.setDatabaseUrl("https://myDatabaseUrl")
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.build();
FirebaseApp.initializeApp(options);
flagForConnectionWithFirebase=true;
LOGGER.info("Options are:: "+options);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
final FirebaseDatabase database =
FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference(url);
String key=ref.push().getKey();
ref.child(key).setValueAsync(users);
After a long search I found that the server was not sync with centralised time zone. post doing that code run successfully on testing environment as well.
I found what seems to be quite a common problem that nobody cares to resolve and it is that there an dependency conflict in one of the Firebase dependencies
<groupId>com.vaadin.external.google</groupId>
<artifactId>android-json</artifactId>
It can be solved by excluding the dependency from Spring Boot Test and the pring-boot-configuration-processor. Now I am having some problems when running test, still cannot tell if they are related.
Related
Searched a lot but there is no precise answer on how to get started with dialogflow in spring boot.
Aim: To detect intent from GDF knowledgebase and return back the response.
What I have done so far:
Tried executing this code https://github.com/googleapis/java-dialogflow/blob/HEAD/samples/snippets/src/main/java/com/example/dialogflow/DetectIntentTexts.java
by creating a main app.
App.java
package com.example.dialogflow;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class App {
public static void main(String[] args) {
DetectIntentTexts theDetectIntentTexts = new DetectIntentTexts();
String projectId = "abc";
String sessionId = "xyz";
String lang = "en";
List<String> myTexts = new ArrayList<>();
myTexts.add("hi");
String ans = null;
try {
ans = String.valueOf(theDetectIntentTexts.detectIntentTexts(projectId, myTexts, sessionId, lang));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Bot reply:" + ans);
}
}
But it fails to run.
I have my service account GCP set in local machine and export GOOGLE_APPLICATION_CREDENTIALS=/path/to/your-project-credentials.json is set too
Any help would be appreciated.
Finally was able to solve it.
Steps:
First run
gcloud auth application-default revoke
This will remove user account & service account credentials.
Now login into gcloud using service account credentials.
gcloud auth activate-service-account --key-file=key.json
Wonder why we have to revoke user account credentials because keeping both the accounts and activating service account didn't work.
Now it works.
FileInputStream serviceAccount =
new FileInputStream("push-manager-app/src/main/resources/serviceAccountKey.json");
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl("https://test1-use.firebaseio.com")
.build();
FirebaseApp.initializeApp(options);
The above code for Firebase connector is working fine. But in openshift environment I can't commit serviceAccountKey.json in resources as it will be different for different environments. I can get it as String from openshift configmap in each environment.
For running this block of code I need to convert String in FileInputStream. I'm not sure how to do it. I have one workaround where I can read String, generate file and use it. But I wanted to use the right way. I checked Firebase API for other options but it can't even handle InputStream.
String json = "xxxxxx";
InputStream stream = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8));
private static InputStream getFile() {
return FireBaseService.class.getResourceAsStream("/dataCred.json");
}
private static final String DATABASE_URL = "DATABASE_URL";
public static void initiainzeSDK() {
try {
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(getFile()))
.setDatabaseUrl(DATABASE_URL)
.build();
FirebaseApp.initializeApp(options);
// Initialize the default app
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
make sure ur json file not wrong syntax
The core issue I have right now, is when I run the Dataflow pipeline deployed to Google Cloud Dataflow, I get the error:
java.lang.IllegalStateException: FirebaseApp with name [DEFAULT] doesn't exist.
If I run the same pipeline locally, it all works. So I SUSPECT either an authentication issue, or an environment issue.
Code bits:
The DEPLOY and REAL variables are to control whether or not to push to Cloud (or run locally) and whether or not to use my Pub/Sub source, or use moc'd data. Switching between moc'd and pub/sub data doesn't seem to have an effect on the Firestore situation at all. Only the deploy or not does.
The main() piece where I'm initializing the Firestore application:
public class BreakingDataTransactions {
// When true, this pulls from the specified Pub/Sub topic
static Boolean REAL = true;
// when set to true the job gets deployed to Cloud Dataflow
static Boolean DEPLOY = true;
public static void main(String[] args) {
// validate our env vars
if (GlobalVars.projectId == null ||
GlobalVars.pubsubTopic == null ||
GlobalVars.gcsBucket == null ||
GlobalVars.region == null) {
System.out.println("You have to set environment variables for project (BREAKING_PROJECT), pubsub topic (BREAKING_PUBSUB), region (BREAKING_REGION) and Cloud Storage bucket for staging (BREAKING_DATAFLOW_BUCKET) in order to deploy this pipeline.");
System.exit(1);
}
// Initialize our Firestore instance
try {
GoogleCredentials credentials = GoogleCredentials.getApplicationDefault();
System.out.println("*************************");
System.out.println(credentials);
FirebaseOptions firebaseOptions =
new FirebaseOptions.Builder()
.setCredentials(credentials)
.setProjectId(GlobalVars.projectId)
.build();
FirebaseApp firebaseApp = FirebaseApp.initializeApp(firebaseOptions);
} catch (IOException e) {
e.printStackTrace();
}
// Start dataflow pipeline
DataflowPipelineOptions options =
PipelineOptionsFactory.create().as(DataflowPipelineOptions.class);
options.setProject(GlobalVars.projectId);
if (DEPLOY) {
options.setRunner(DataflowRunner.class);
options.setTempLocation(GlobalVars.gcsBucket);
options.setRegion(GlobalVars.region);
}
Pipeline p = Pipeline.create(options);
And the piece where I'm processing things:
PCollection<Data> dataCollection =
jsonStrings
.apply(ParDo.of(JSONToPOJO.create(Data.class)))
.setCoder(AvroCoder.of(Data.class));
PCollection<Result> result =
dataCollection
.apply(Window.into(FixedWindows.of(Duration.standardSeconds(1))))
.apply(WithKeys.of(x -> x.operation + "-" + x.job_id))
.setCoder(KvCoder.of(StringUtf8Coder.of(), AvroCoder.of(Data.class)))
.apply(Combine.<String, Data, Result>perKey(new DataAnalysis()))
.apply(Reify.windowsInValue())
.apply(MapElements.into(TypeDescriptor.of(Result.class))
.<KV<String, ValueInSingleWindow<Result>>>via(
x -> {
Result r = new Result();
String key = x.getKey();
r.query_action = key.substring(0, key.indexOf("-"));
r.job_id = key.substring(key.indexOf("-") + 1);
r.average_latency = x.getValue().getValue().average_latency;
r.failure_percent = x.getValue().getValue().failure_percent;
r.timestamp = x.getValue().getTimestamp().getMillis();
return r;
}));
// this node will (hopefully) actually write out to Firestore
result.apply(ParDo.of(new FireStoreOutput()));
And finally, the FireStoreOutput class:
public static class FireStoreOutput extends DoFn<Result, String> {
Firestore db;
#ProcessElement
public void processElement(#Element Result result) {
db = FirestoreClient.getFirestore();
DocumentReference docRef = db.collection("events")
.document("next2020")
.collection("transactions")
.document(result.job_id)
.collection("transactions")
.document();
//System.out.println(docRef.getId());
// Add document data with id "alovelace" using a hashmap
Map<String, Object> data = new HashMap<>();
data.put("failure_percent", result.failure_percent);
data.put("average_latency", result.average_latency);
data.put("query_action", result.query_action);
data.put("timestamp", result.timestamp);
// asynchronously write data
ApiFuture<WriteResult> writeResult = docRef.set(data);
try {
writeResult.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
;
}
}
The error occurs on the line: db = FirestoreClient.getFirestore();
I'm deploying the Dataflow job with the --serviceAccount flag specifying a service account that has permissions to do all the things.
So unless the GoogleCredentials credentials = GoogleCredentials.getApplicationDefault(); somehow doesn't work (but you see the print statement there, and it does correctly print out the credentials on build) that isn't it.
BUT, that only happens at build time...so I'm wondering if I have a persistence problem, where it initializes fine at build time, but when the job is actually running in the Cloud, it loses the initialization between the deployment and the processing. And if that's the case, how do I solve that problem?
Thanks!
Okay, I found a solution... The biggest issue was that my DAG's PCollection was split into two thread paths. I have two types of operations "read" and "write" so those results were each sending a PCollection to my FirestoreOut class, which is where I was attempting to initialize the Firestore app, resulting in the already initialized problem.
HOWEVER, making my db object a synchronized static object, and instituting a synchronized getDB() method where I initialize only if it's not set yet worked. Final updated relevant code for the FireStoreOut piece:
public static class FireStoreOutput extends DoFn<Result, String> {
static Firestore db;
public static synchronized Firestore getDB() {
if (db == null) {
System.out.println("I'm being called");
// Initialize our Firestore instance
try {
GoogleCredentials credentials = GoogleCredentials.getApplicationDefault();
System.out.println("*************************");
System.out.println(credentials);
FirebaseOptions firebaseOptions =
new FirebaseOptions.Builder()
.setCredentials(credentials)
.setProjectId(GlobalVars.projectId)
.build();
FirebaseApp firebaseApp = FirebaseApp.initializeApp(firebaseOptions);
} catch (IOException e) {
e.printStackTrace();
}
db = FirestoreClient.getFirestore();
}
return db;
}
#ProcessElement
public void processElement(#Element Result result) {
DocumentReference docRef = getDB().collection("events")
.document("next2020")
.collection("transactions")
.document(result.job_id)
.collection("transactions")
.document();
I am developing an android application using google endpoints and google app engine. My backend does not seem to actually be doing anything. It appears as if nothing is being saved to the datastore and therefore nothing can be retrieved from it.
Here are some of the Api methods I have written in endpoints that are not working:
private static String getUserId(User user) {
String userId = user.getUserId();
if (userId == null) {
AppEngineUser appEngineUser = new AppEngineUser(user);
ofy().save().entity(appEngineUser).now();
// Begin new session for not using session cache.
Objectify objectify = ofy().factory().begin();
AppEngineUser savedUser = objectify.load().key(appEngineUser.getKey()).now();
userId = savedUser.getUser().getUserId();
}
return userId;
}
#ApiMethod(name = "saveProfile", path = "profile", httpMethod = ApiMethod.HttpMethod.POST)
public Profile saveProfile(final User user, final ProfileForm profileForm) throws UnauthorizedException {
if(user == null) {
throw new UnauthorizedException("Authorization required.");
}
String firstName = profileForm.getFirstName();
String surname = profileForm.getLastName();
String userEmail = user.getEmail();
int year = profileForm.getYear();
int month = profileForm.getMonth();
int day = profileForm.getDay();
Profile profile = ofy().load().key(Key.create(Profile.class, getUserId(user))).now();
if (profile == null) {
// the user does not have a profile and is creating one for the first time
profile = new Profile(getUserId(user), firstName, surname, userEmail, year, month, day);
} else {
profile.update(firstName, surname, userEmail, year, month, day);
}
ofy().save().entity(profile).now();
return profile;
}
#ApiMethod(name = "getProfile", path = "profile", httpMethod = ApiMethod.HttpMethod.GET)
public Profile getProfile(User user) throws UnauthorizedException {
if (user == null) {
throw new UnauthorizedException("Authentication required.");
}
return ofy().load().key(Key.create(Profile.class, getUserId(user))).now();
}
}
The profile class has the #Entity annotation and is registered with objectify in a static block like so:
static {
factory().register(AppEngineUser.class);
factory().register(Profile.class);
}
The userId is generated by GAE through
com.google.appengine.api.users.User
and the userId property is a String with the #Index annotation.
I am also confused by the api explorer and how it is responding to these methods. Whenever I call the saveProfile api method, a profile object is returned with a userId of 0 and an email of "example#example.com" although I believe this is the default email when running on localhost.
I am also running api explorer over HTTP,Google says this "can cause problems." Is this the reason why nothing is working. I have had to load unsafe scripts just for me to use my api, but maybe it does not work as it is hosted over HTTP instead of HTTPS.
Is this entire problem of not being able to fully test my methods due to a fundamental flaw in my understanding of GAE or is due to me running on localhost. If it is the latter perhaps I should deploy to Appspot and things may run smoother.
If there is anything extra you need to help, please just ask.
Thank you!
Check your logs in the developers console. It records all API methods that you execute and will show if any have any errors.
Since you are getting example#example.com as the email of the User this leads me to believe the User is not being injected by GAE. This is probably because you are doing something wrong client side (e.g. in Android). Make sure your Android app correctly asks to log a user in with Google and pass those credentials to your builder object in Android.
If you are executing your API method via the api explorer, you need to be logged in as a google user first for that User object to be populated in your method (I think you already know that).
In short, check your logs and your client code.
Good afternoon all!
I use PayPal REST API java sdk and I want to have different configurations for different environments of my application. Here is how I'm trying to do so:
private static boolean IS_PRODUCTION = false;
private static String PAYPAL_ACCESS_TOKEN;
private static void initPayPal() {
InputStream is = null;
try {
is = ApplicationConfig.class.getResourceAsStream(
IS_PRODUCTION? "/my_paypal_sdk_config.properties" : "/my_paypal_sdk_config_test.properties");
PayPalResource.initConfig(is);
String clientID = ConfigManager.getInstance().getConfigurationMap().get("clientID");
String clientSecret = ConfigManager.getInstance().getConfigurationMap().get("clientSecret");
PAYPAL_ACCESS_TOKEN = new OAuthTokenCredential(clientID, clientSecret).getAccessToken();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
IOUtils.closeQuietly(is);
}
}
and while trying to get the clientID I have
java.io.IOException: Resource 'sdk_config.properties' could not be found
Strange behavior - I thought I've just configured the sdk to use my own properties file.
Please advice how could I set up those settings properly!
So here is the solution I found:
Create an empty sdk_config.properties file in default location
Load your own properties:
private static void initPayPal() {
InputStream is = null;
try {
is = ApplicationConfig.class.getResourceAsStream(
IS_PRODUCTION ? "/my_paypal_sdk_config.properties" : "/my_paypal_sdk_config_test.properties");
Properties props = new Properties();
props.load(is);
PayPalResource.initConfig(props);
ConfigManager.getInstance().load(props);
String clientID = ConfigManager.getInstance().getConfigurationMap().get("clientID");
String clientSecret = ConfigManager.getInstance().getConfigurationMap().get("clientSecret");
PAYPAL_ACCESS_TOKEN = new OAuthTokenCredential(clientID, clientSecret).getAccessToken();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
IOUtils.closeQuietly(is);
}
}
We have made some good improvements to the PayPal Java SDK on integration steps. We are removing the need for sdk_config.properties file as they do not work as well, specially for multi-configuration settings.
Now, all you do is create an APIContext instance with clientId, clientSecret, and mode. You pass that context object for any API operation from there on.
Here is how the code would look like for different configurations:
APIContext defaultContext = new APIContext(clientId1, clientSecret1, "sandbox");
APIContext sandboxContext = new APIContext(clientId2, clientSecret2, "sandbox");
APIContext someOtherContext = new APIContext(clientId3, clientSecret3, "live");
APIContext liveContext = new APIContext(clientId, clientSecret, "live");
// Now pass any of the above context in these calls, and it would use those configurations.
Payment payment = new Payment();
// Fill in all the details.
payment.create(defaultContext);
// Replace that defaultContext with any of those other contexts.
Here is the wiki page explaining that: https://github.com/paypal/PayPal-Java-SDK/wiki/Making-First-Call
I had the same error with SDK 0.11 version. I use my own properties file, but code still looked for "sdk_config.properties". I put it into root in my CLASSPATH, but still got the same error. Then I made obvious and horrible solution: put empty "sdk_config.properties" into "rest-api-sdk-0.11.0.jar" library. This street magic solved my problem.