My goal (background info)
I want to develop a java microservice on cumulocity. It should be able to do the following:
I would send "112233" to the microservice as follows:
https://myTenant.cumulocity.com/service/my-application-name/decode?data=112233
The microservice should then split the data into "11" for the first measurement and "22" for the second measurement etc. These measurements would be POSTed to cumulocity.
My problem
I am now stuck on getting the Hello, microservice tutorial to work. I can't deploy the microservice (zip file) to cumulocity.
"error":"security/Forbidden","info":"https://www.cumulocity.com/guides/reference-guide/#error_reporting","message":"Access is denied"} (I am an admin user.)
I also tried to upload the zip file via the website, this created a HOSTED application instead of a MICROSERVICE. Uploading my zip via a POST request to a HOSTED application actually works (which I obviously don't need).
I suspect that I get the "access denied" error cause cumulocity thinks that I upload a HOSTED application to a MICROSERVICE.
What I've done so far
Code side
I downloaded the hello-world-microservice example from the cumulocity bitbucket development branch. (This code is not available on the default branch).
I changed the cumulocity versions to 9.3.0, only this version seems to exist.
The HelloWorldMain.java is unedited
This is my cumulocity.json manifest file: (the roles make no difference)
{
"apiVersion":"1",
"type":"MICROSERVICE",
"version":"#project.version#",
"availability":"PRIVATE",
"provider":{
"name":"Cumulocity GmbH"
},
"isolation":"MULTI_TENANT",
"requiredRoles":[
"ROLE_APPLICATION_MANAGEMENT_ADMIN",
"ROLE_MEASUREMENT_ADMIN",
"ROLE_INVENTORY_ADMIN"
],
"roles":[
"ROLE_APPLICATION_MANAGEMENT_ADMIN",
"ROLE_MEASUREMENT_ADMIN",
"ROLE_INVENTORY_ADMIN"
],
"livenessProbe":{
"httpGet":{
"path":"/health",
"port":80
},
"initialDelaySeconds":15,
"periodSeconds":10
},
"readinessProbe":{
"httpGet":{
"path":"/health",
"port":80
}
}
}
This is my application.properties file
application.name=my-application-name
server.port=80
C8Y.baseURL=https://myTenant.cumulocity.com
C8Y.bootstrap.tenant=myTenant
C8Y.bootstrap.user=servicebootstrap_my-application-name
C8Y.bootstrap.password={SECRET_BOOTSTRAP_PASSW}
C8Y.user={MY_USERNAME}
C8Y.password={SECRET_PASSW}
C8Y.bootstrap.register=true
C8Y.microservice.isolation=MULTI_TENANT
C8Y.bootstrap.initialDelay=10000
Cumulocity side
I successfully created a microservice application,
GET https://myTenant.cumulocity.com/application/applications/5886 returns:
{
"availability":"PRIVATE",
"id":"5886",
"key":"my-application-key",
"manifest":{
"imports":[
],
"noAppSwitcher":true
},
"name":"my-application-name",
"owner":{
"self":"https://myTenant.cumulocity.com/tenant/tenants/myTenant",
"tenant":{
"id":"myTenant"
}
},
"requiredRoles":[
"ROLE_APPLICATION_MANAGEMENT_ADMIN",
"ROLE_MEASUREMENT_ADMIN",
"ROLE_INVENTORY_ADMIN"
],
"roles":[
"ROLE_APPLICATION_MANAGEMENT_ADMIN",
"ROLE_MEASUREMENT_ADMIN",
"ROLE_INVENTORY_ADMIN"
],
"self":"https://myTenant.cumulocity.com/application/applications/5886",
"type":"MICROSERVICE"
}
I also successfully subscribed to this application.
When I try to upload the zip file to cumulocity, I get this error:
"error":"security/Forbidden","info":"https://www.cumulocity.com/guides/reference-guide/#error_reporting","message":"Access is denied"}
(Uploading to a HOSTED type application works fine, but I don't want that.)
note: I also tried to use the microservice deploy script, this gave the same result as doing everything manually.
Trying to run it locally
Since I couldn't get it to work on the cumulocity platform, I tried to run it locally via docker. I ran it with this command:
docker run -e "C8Y_MICROSERVICE_ISOLATION=MULTI_TENANT" 10aa0b73ddb3
note: I had to add the "C8Y_MICROSERVICE_ISOLATION=MULTI_TENANT" environment variable. if I didn't add this, I'd get credential/permission issues. This seems weird to me, since all other info is read from the application.properties file except for this one.
I have no errors when running this image on a local docker.
According to the Hello, microservice tutorial, I should be able to request curl -H "Authorization: {AUTHORIZATION}" https://myTenant.cumulocity.com/service/my-application-name/hello?who=me
This returns:
{"error":"microservice/Not Found","info":"https://www.cumulocity.com/guides/reference-guide/#error_reporting","message":"Microservice my-application-name not found."}
Back to the questions
Has anyone else had difficulties with setting up a microservice on cumulocity?
Is there something I'm totally overseeing?
The microservice hosting needs to be assigned to your tenant otherwise it won't work and the API in that case will return forbidden. So it might be that it is no issue with your user but that your tenant has the feature not activated.
Related
While working through a programming book, I implemented a local REST service running in Tomact on port 8081 in the folder webapi (http://localhost:8081/lwchapter1/webapi/user/login). When running a request in Postman I get an error:
Could not send request
Error: connect ECONNREFUSED 127.0.0.1:8081
I dont understand, how to debug this and therefore kindly ask for help!
The service is implemented (as far as I understand) like this:
Postman to test the API
Tomcat to provide the service
compiled War File
maven as a build tool
java class listening for POST requests in a specific folder
The java project compiles, undeploy/ deploy works and the war file is in the tomcat folder, tomcat is running.
Edit: I found a developer console in Postman giving additional information. Unfortunately this doesn't help either since there is no parameter in the request:
Could not find on r. Missing or invalid parameter.
No revision id found for response
I found the solution by:
checking which ports are open and listened by using
netstat -a -n -p tcp | grep 127.0.0.1*
in the terminal
understanding in which folder the REST service listens by checking the actual java program
Thanks to #MattVickery for your kind help, I really appreciated it!
I have an angularJS application with springboot and it runs on 8090 port number with "index.htm" file. Like below ;
192.168.1.25:8090/index.htm
I just googled about the changing port and I did the change with 80 port number so I can open the web page with
192.168.1.25/index.htm
But, in google there are plenty of angular result and they tell me to change those settings with in angular.json file. I created a temporary angular project and did those with successfully. But, I could not figure out about the angularjs part. I checked the project and I could not find any file like angular.json. After that checking the springboot, I found this part of where I can open the web page with the above second URL address ;
192.168.1.25/index.htm
The code of Spring Boot part is below (There is where I can change the port number) :
Those ones did the trick by the way.
config.getMemberAttributeConfig().setStringAttribute(ServerService.MANAGEMENT_URL_PREFIX, ":80/index.htm");
config.getMemberAttributeConfig().setStringAttribute(ServerService.MANAGEMENT_URL_PREFIX, ":80");
After those steps, I can easily serve my angularjs app on 80 port and start to thinking about editing the /etc/hosts file on the server machine as :
192.168.1.25/index.htm xyz.com
I did reboot when I finished the editing part and I tried again to write xyz.com on firefox browser it does not go to my application.
I am still looking on the google and still could not find any solutions about this problem.
Any help will be really appreciated.
Format for hosts file is
#<ip> <hostname that resolve to the ip>
192.168.1.25 xyz.com
# or a list of names
192.168.1.25 xyz.com myapp.xyz.com
You do not put any port numbers or path parts in it. This will obviously only work if you edit the hosts file on all the computers
you are indending to access the site from and not necessarily on the host running the application itself.
That being said, you should probably read on supported Spring Boot properties because starting an application server on a specific port should be as easy as adding application.properties file in java resources with the following line:
server.port=80
One of my Microservice [MS1] checks another Microservice [MS2] at startup, if MS2 is running or not. If MS2 is running MS1 will start else fails to start.
But currently I am running MS2 on my local machine which takes a huge amount of RAM ans slow down my machine.
Is there any mechanism so that when MS1 starts and look-up for MS2 it seems that MS2 is running without actually running real MS2?
Update :
Let's assume MS2 is running on localhost:1234 and now MS1 will connect to it using REST.
You can have a look at WireMock which is a simulator of HTTP API so it will be suitable for local development. When using it you will be able to mimic a microservice as if it was running as a standalone microservice on given host and port.
You can run it both as a standalone process and as a part of your spring application.
Option 1 - configuring standalone wiremock server :
Download Wiremock Standalone jar
Run standalone server on localhost with port 1234 :
java -jar wiremock-standalone-2.24.0.jar --port 1234
Configure your MS1 microservice to use localhost:1234 as your MS2 host.
Mock your MS2(mocked with wiremock) endpoint with some response :
curl -X POST --data '{ "request": { "url": "/yourendpoint", "method": "GET" }, "response": { "status": 200, "body": "Response" }}' http://localhost:1234/__admin/mappings/new
Here we make a mock that when you hit on your mocked server on /yourendpoint with HTTP GET you will receive text Response as response.
Now when you hit with GET on localhost:1234/yourendpoint you get your mocked response :
curl http://localhost:1234/yourendpoint
Response
Full example can be found at Wiremock Standalone docs
Option 2 - configuring WireMock server in your Spring app :
Add WireMock dependency to your project (watch out to add it not only to test scope)
Create a Spring bean used to set up your server :
#Component
public class CustomMicroserviceMock {
private WireMockServer wireMockServer;
public CustomMicroserviceMock() {
wireMockServer = new WireMockServer(options().port(1234));
wireMockServer.stubFor(get(urlEqualTo("/yourendpoint"))
.willReturn(aResponse()
.withHeader("Content-Type", "text/plain")
.withBody("Response")));
wireMockServer.start();
}
#PreDestroy
void preDestroy() {
wireMockServer.stop();
}
}
When we hit localhost:1234/yourendpoint we get response : Response
This is just a POC how it could look like but it works in both cases.
I recommend using WireMock as a standalone service in your local machine, or if you
are familiar with docker you can check the wiremock docker image :
https://hub.docker.com/r/rodolpheche/wiremock/
I'm using it for my development and testing, it's really a strong stubbing solution :)
Best of luck
I am trying to setup an application server for AWS Lambda but on a local network so that an application won't have to go out to the internet to execute. I would prefer to use a linux box and my programming environment is Java.
The skill from the echo will execute and then communicate with the local server rather than going out to the internet and communicating with Amazon's application server.
My question is this: How do I setup the application server to handle the skill? I've done the example from Amazon, do I only need to have the linux box run the Java application or is there more to the setup than that? I see there are AMIs (Amazon Machine Images) but can I deploy those locally or are they only for use on the AWS console?
Any insight into this would be great, thank you.
So this is how usual interaction between echo works:
User--->Echo--->Skill--->(Internet)Applicaton server (I'm using Amazon hosted AWS lambda)
I would like to use :
User--->Echo--->Skill--->(LAN)Application server (without ever using the internet).
Currently I have setup echo and a skill but no application server on the LAN. What do I need for the application server? JAWS and something else?
I'm not sure if this question is still relevant or not, but I'm using DEEP Framework to test the code locally and/or deploy it on AWS Lambda. Check this out:
npm install deepify -g
deepify run-lambda --help
run-lambda#1.6.8 - Run Lambda function locally
Usage example: deepify run-lambda path/to/the/lambda -e='{"Name":"John Doe"}'
Arguments:
path: The path to the Lambda (directory of handler itself)
Options:
--event|-e: JSON string used as the Lambda payload
--skip-frontend-build|-f: Skip picking up _build path from the microservices Frontend
--db-server|-l: Local DynamoDB server implementation (ex. LocalDynamo, Dynalite)
--version|-v: Prints command version
--help|-h: Prints command help
Also, you might want consider using the server option:
deepify server --help
server#1.6.9 - Run local development server
Usage example: deepify server path/to/web_app -o
Arguments:
path: The path to the Lambda (directory of handler itself)
Options:
--build-path|-b: The path to the build (in order to pick up config)
--skip-frontend-build|-f: Skip picking up _build path from the microservices Frontend
--skip-backend-build|-s: Skip building backend (dependencies installation in Lambdas and linking aws-sdk)
--skip-build-hook|-h: Skip running build hook (hook.build.js)
--port|-p: Port to listen to
--db-server|-l: Local DynamoDB server implementation (ex. LocalDynamo, Dynalite)
--open-browser|-o: Open browser after the server starts
--version|-v: Prints command version
--help|-h: Prints command help
Disclosure: I am one of the contributors to this framework
We have a web application (Java spring mvc project).
Our server returns jsons via REST API.
here is a response example from our QA env:
{currency: "EURO", symbol: "€", multiplier: 1}
here is the same response from a different enviornment (the Dev):
{currency: "EURO", symbol: "�", multiplier: 1}
Any ideas why this may happen?
OK - so my issue was with the build machine (Jenkins) which is running on ubuntu.
All the envs, that the build machine compiled and deployed our app had the issue.
I had to change the gradle tasks to be compiled with
tasks.withType(JavaCompile) { options.encoding = 'Cp1252' }
(Since we develop on windows env and thats the default).
Cheers
It's because your browser is painting out the font after all the work has been done to it in the background (on the server). This means you could have it encoded correctly at some point, but once the browser gets it, it is no longer encoded, and showing a character the browser doesn't understand.
You need to run one more pass with JavaScript on the browser side. A simple replace on the string with the proper encoding will fix it.