GCP Pub/Sub throws "The Application Default Credentials are not available" - eclipse

I am trying to publish to Google Pub/Sub topic using the following:
ProjectTopicName topicName = ProjectTopicName.of("my-project-id", "my-topic-id");
Publisher publisher = null;
try {
// Create a publisher instance with default settings bound to the topic
publisher = Publisher.newBuilder(topicName).build();
List<String> messages = Arrays.asList("first message", "second message");
for (final String message : messages) {
ByteString data = ByteString.copyFromUtf8(message);
PubsubMessage pubsubMessage = PubsubMessage.newBuilder().setData(data).build();
// Once published, returns a server-assigned message id (unique within the topic)
ApiFuture<String> future = publisher.publish(pubsubMessage);
// Add an asynchronous callback to handle success / failure
ApiFutures.addCallback(
future,
new ApiFutureCallback<String>() {
#Override
public void onFailure(Throwable throwable) {
if (throwable instanceof ApiException) {
ApiException apiException = ((ApiException) throwable);
// details on the API exception
System.out.println(apiException.getStatusCode().getCode());
System.out.println(apiException.isRetryable());
}
System.out.println("Error publishing message : " + message);
}
#Override
public void onSuccess(String messageId) {
// Once published, returns server-assigned message ids (unique within the topic)
System.out.println(messageId);
}
},
MoreExecutors.directExecutor());
}
} finally {
if (publisher != null) {
// When finished with the publisher, shutdown to free up resources.
publisher.shutdown();
publisher.awaitTermination(1, TimeUnit.MINUTES);
}
}
I have changed the default values you see here to the particulars of the account I am hitting.
The environment variable points to the JSON file containing the pub/sub authentication credentials:
GOOGLE_APPLICATION_CREDENTIALS
was set using:
export GOOGLE_APPLICATION_CREDENTIALS=path/to/file.json
and verified with echo $GOOGLE_APPLICATION_CREDENTIALS - after a reboot.
But I am still encountering:
The Application Default Credentials are not available. They are available
if running in Google Compute Engine. Otherwise, the environment variable
GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining
the credentials. See https://developers.google.com/accounts/docs/application-
default-credentials for more information.
I believe this is related to the default environment that the application is running in, or rather what GCP object thinks the context is -runningOnComputeEngine:
com.google.auth.oauth2.ComputeEngineCredentials runningOnComputeEngine
INFO: Failed to detect whether we are running on Google Compute Engine.
also, a dialog displayed:
Unable to launch App Engine Server
Cannot determine server execution context
and there are no Google Cloud Platform settings in project (Eclipse 2019-3):
This is not an App Engine application.
How to set the environment that GCP objects point to -> Non App Engine.
For reference:
Server to Server (link in error message)
Publish
Google Cloud Tools for Eclipse
Java 7 application
Mac OS (Sierra)
The file permissions are set that app can read the file.

Google's documentation on this is terrible - it does not mention this anywhere.
The answer is to use:
// create a credentials provider
CredentialsProvider credentialsProvider = FixedCredentialsProvider.create(ServiceAccountCredentials.fromStream(new FileInputStream(Constants.PUB_SUB_KEY)));
// apply credentials provider when creating publisher
publisher = Publisher.newBuilder(topicName).setCredentialsProvider(credentialsProvider).build();
The Environment variable usage is either deprecated or the documentation is flat out wrong, or I'm missing something,... which is entirely possible given the poor documentation.

Related

Failed to load API definition Fetch Error, when deployed but fine on localhost

I am upgrading my api from netcore2.1 to 3.1
When I run on localhost the UI works fine.
When I deploy via Azure DevOps and go to the myapplication/myapi/swagger.html url I get
Failed to load API definition
Fetch Error
Service Unavailable /myapi/swagger/v1/swagger/json
Yet I can see the json at
myapplication/myapi/swagger/v1/swagger.json
I have the following
public static IApplicationBuilder UseSwaggerDocumentation(this IApplicationBuilder app)
{
app.UseSwagger(c =>
c.RouteTemplate = "myapi/swagger/{documentName}/swagger.json"
);
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/myapi/swagger/v1/swagger.json", "Versioned API v1.0");
c.RoutePrefix = "myapi/swagger";
});
return app;
}
I am using
Swashbuckle.AspNetCore (5.2.0)
I found the following worked.
public static IApplicationBuilder UseSwaggerDocumentation(this IApplicationBuilder app)
{
app.UseSwagger(c =>
c.RouteTemplate = "myapi/{documentName}/swagger.json"
);
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("./v1/swagger.json", "Versioned API v1.0");
c.RoutePrefix = "myapi";
});
return app;
}
The docs state
If using directories with IIS or a reverse proxy, set the Swagger
endpoint to a relative path using the ./ prefix. For example,
./swagger/v1/swagger.json. Using /swagger/v1/swagger.json instructs
the app to look for the JSON file at the true root of the URL (plus
the route prefix, if used). For example, use
http://localhost://swagger/v1/swagger.json instead
of
http://localhost:///swagger/v1/swagger.json.
However unfortunately my solution doesn't work with Autorest.
Thus I asked another question

After Deploying, ASP.NET application showing Internal server error

I deployed my ASP.NET application to a remote server with a hosting company, and when i try to send data from Postman, i get the internal server error with no definite error message. I have set custom error mode to off in the web config file. please can anyone help me? I have checked for several solutions but nothing.
PS: i am new to ASP.NET deployment with other companies apart from Azure
In this case, you should log error to file to see what issues in deployment mode.
This way i implemented global error log.
public class ExceptionHandlingAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
//Log Critical errors
// You can use log4net library and configure log folder
}
}
In WebApiConfig.cs file you register it.
public static void Register(HttpConfiguration config)
{
// .....
config.Filters.Add(new ExceptionHandlingAttribute());
}

authentication with Xamarin. Android and Microsoft.Azure.Mobile.Client Microsoft provider error

I had a code that worked unlit few days ago: this is an xamarin.android activity code
[Activity(Label = "AuthSample", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
Button login;
//Mobile Service Client reference
private MobileServiceClient client;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Create the Mobile Service Client instance, using the provided
// Mobile Service URL and key
client = new MobileServiceClient("https://XXXXXXX.azurewebsites.net");
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
login = FindViewById<Button>(Resource.Id.buttonLoginUser);
login.Click += onLoginClick;
}
private async void onLoginClick(object sender, EventArgs e)
{
// Load data only after authentication succeeds.
if (await Authenticate())
{
}
}
// Define a authenticated user.
private MobileServiceUser user;
private async Task<bool> Authenticate()
{
var success = false;
try
{
// Sign in with Microsoft login using a server-managed flow.
user = await client.LoginAsync(this,
MobileServiceAuthenticationProvider.MicrosoftAccount);
CreateAndShowDialog(string.Format("you are now logged in - {0}",
user.UserId), "Logged in!");
success = true;
}
catch (Exception ex)
{
CreateAndShowDialog(ex, "Authentication failed");
}
return success;
}
private void CreateAndShowDialog(Exception exception, String title)
{
CreateAndShowDialog(exception.Message, title);
}
private void CreateAndShowDialog(string message, string title)
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.SetMessage(message);
builder.SetTitle(title);
builder.Create().Show();
}
}
i did all the instruction in the tutorial.
the LoginAsync redirect me to the Microsoft login page, i am able to authenticate and after a successful authentication i get this error : "the page cannot be displayed because an internal server error has occured"
i am working with 3.1 azure sdk version
According to your description, I assumed that you could follow the steps below to troubleshoot this issue.
For Node.js backend
You could leverage App Service Editor or kudu for create the iisnode.yml file under root folder (D:\home\site\wwwroot) if not exists. Then add the following settings for enable logging to debug a Node.js web app in azure app service:
loggingEnabled: true
logDirectory: iisnode
Additionally, here is a similar issue about enable node.js logging, you could refer to it. Also, for more details about kudu and app service editor, you could refer to here.
For C# backend
you could edit App_Start\Startup.MobileApp.cs file and configure the IncludeErrorDetailPolicy as follows for capturing the error details:
HttpConfiguration config = new HttpConfiguration();
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
For a simple way, you could access https://{your-app-name}.azurewebsites.net/.auth/login/{provider-name} via the browser, then check the detailed error message for locating the specific error.
UPDATE:
Based on your address, I checked your app and found I could log with my Microsoft Account via the browser. Then I checked with your table endpoint and found the follow error:
https://{your-app-name}.azurewebsites.net/tables/todoitem?ZUMO-API-VERSION=2.0.0
message: "An error has occurred.",
exceptionMessage: "A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 52 - Unable to locate a Local Database Runtime installation. Verify that SQL Server Express is properly installed and that the Local Database Runtime feature is enabled.)",
exceptionType: "System.Data.SqlClient.SqlException",
As I known, when following the quickstart to create the data store for your backend, downloading the C# backend, then deploy the backend to moible app. At this point, your created connection string via azure portal would not be exposed to your ASP.NET application, and the default connection string would use the localdb, you need to edit the Web.config file before deploying to azure mobile app as follows:
<connectionStrings>
<add name="MS_TableConnectionString" connectionString="Data Source=tcp:{your-sqlserver-name}.database.windows.net,1433;Initial Catalog={db-name};User ID={user-id};Password={password}" providerName="System.Data.SqlClient" />
</connectionStrings>
Or configure the connection string when deploy your app to azure mobile app via VS as follows:
It seems that there was a problem in azure or in Microsoft authentication.
after two days of frustration everything just started to work again!!

loadbalanced ribbon client initialization against discovery service (eureka)

I have service which runs some init scripts after application startup (implemented with ApplicationListener<ApplicationReadyEvent>). In this scripts I need to call another services with RestTemplate which is #LoadBalanced. When the call to service is invoked there's no information about instances of remote service because discovery server was not contacted at that time (I guess).
java.lang.IllegalStateException: No instances available for api-service
at org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.execute(RibbonLoadBalancerClient.java:79)
So is there way how to get list of available services from discovery server at application startup, before my init script will execute?
Thanks
edit:
The problem is more related to fact, that in current environment (dev) all services are tied together in one service (api-service). So from within api-service I'm trying to call #LoadBalanced client api-service which doesn't know about self? Can I register some listener or something similar to know when api-service (self) will be available?
here are the sample applications. I'm mainly interested how to have working this method
edit2:
Now there could be the solution to create EurekaListener
public static class InitializerListener implements EurekaEventListener {
private EurekaClient eurekaClient;
private RestOperations restTemplate;
public InitializerListener(EurekaClient eurekaClient, RestOperations restTemplate) {
this.eurekaClient = eurekaClient;
this.restTemplate = restTemplate;
}
#Override
public void onEvent(EurekaEvent event) {
if (event instanceof StatusChangeEvent) {
if (((StatusChangeEvent) event).getStatus().equals(InstanceInfo.InstanceStatus.UP)) {
ResponseEntity<String> helloResponse = restTemplate.getForEntity("http://api-service/hello-controller/{name}", String.class, "my friend");
logger.debug("Response from controller is {}", helloResponse.getBody());
eurekaClient.unregisterEventListener(this);
}
}
}
}
and then register it like this:
EurekaEventListener initializerListener = new InitializerListener(discoveryClient, restTemplate);
discoveryClient.registerEventListener(initializerListener);
However this is only executed only when application is registered to discovery service first time. Next time when I stop the api-service and run it again, event is not published. Is there any other event which can I catch?
Currently, in Camden and earlier, applications are required to be registered in Eureka before they can query for other applications. Your call is likely too early in the registration lifecycle. There is an InstanceRegisteredEvent that may help. There are plans to work on this in the Dalston release train.

Force installer to fail when ports are not available?

I am using install4j to install an intranet application which requires an HTTP and HTTPS port. I would like to test that these ports are available and warn the user/block the installation until they select unavailable ports.
The only avenue I see for this (besides custom code) is to ensure the windows service fails if the application cannot bind to needed ports, and use a Failure Strategy "Ask user whether to retry or quit on failure". In the web server startup code, I use System.exit(1) if the server cannot bind to ports. However, this does not appear to register as a failure to the installer - the installation proceeds without invoking the failure strategy.
What is the proper approach for signaling failure to the "Start a service" action? Have other people taken an alternate approach to guaranteeing the installation uses available ports?
A good alternate approach I've since found: add a custom code action:
List<Integer> takenPorts = new ArrayList<Integer>();
for (int port : Arrays.asList(80, 443)) {
java.net.ServerSocket socket = null;
try {
socket = new java.net.ServerSocket(port);
} catch (IOException e) {
takenPorts.add(port);
} finally {
if (socket != null) socket.close();
}
}
if (takenPorts.isEmpty()) {
return true;
}
else {
String msg;
if (takenPorts.size() == 2) {
msg = "Ports 80 and 443 must be available for uDiscovery";
}
else {
msg = "Port " + takenPorts.get(0) + " must be available for uDiscovery";
}
context.setVariable("portErrorMessage", msg);
return false;
}
Good explanation of how to wire this up here
All who are just getting an error dialog telling
"com.install4j.runtime.beans.action.control.RunScriptAction failed"
I think that also was the one, Adam got:
In the srciptlet above the variable named portErrorMessage was set.
I also didn't realise that first. The trick is quite simple: You have to insert ${installer:portErrorMessage} in the field "Error message". Doing so, you don't need the Util.showOptionDialog described by Ingo, since that method call opens another, second dialog that has to be acknowledged first, after that the user would have to acknowloedge the dialog from install4j, too.