ibmstocktrader / portfolio Goto Github PK
View Code? Open in Web Editor NEWMicroservice implemented with MicroProfile that persists stock portfolios to JDBC (such as DB2)
License: Apache License 2.0
Microservice implemented with MicroProfile that persists stock portfolios to JDBC (such as DB2)
License: Apache License 2.0
This feels incorrect, everytime I post feedback, the number of free trades I have resets to the value associated with that feedback.
So if I post angry feedback, and I'm granted 3 free trades, then post happy feedback, I'm reset to a single free trade, (which will probably make me angry, and submit more feedback)..
Free trade count for feedback should probably be cumulative, and capped somehow to prevent abuse.
Currently the server is configured to accept JWTs, but also has a basic user registry with roles assigned and groups.
The roles should be coming from the JWT, to avoid embedding user ids and user roles within this service.
This service should only be validating the JWT, using the user id from within the token, and honoring the roles allowed by the token.
[WARNING]
[WARNING] Some problems were encountered while building the effective model for com.stocktrader:portfolio:war:1.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.version' for io.fabric8:docker-maven-plugin is missing. @ line 123, column 21
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
Keys for microservices should be supplied as configuration via k8s secrets, having them present in github kinda defeats the purpose of them being secret.
This is a placeholder issue to track removal of the keys, updating the project to use k8s secret provisioned keys, and adding the documentation to cover the creation of the secrets.
Was seeing the following error in portfolio
WTRN0074E: Exception caught from before_completion synchronization operation: javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.10.v20211216-fe64cd39c3): org.eclipse.persistence.exceptions.DatabaseException\nInternal Exception: org.postgresql.util.PSQLException: ERROR: could not serialize access due to concurrent delete\nError Code: 0\nCall: DELETE FROM STOCK WHERE ((SYMBOL = ?) AND (owner = ?))\n\tbind => [2 parameters bound]\nQuery: DeleteObjectQuery({\"symbol\": \"AMZN\", \"shares\": 5, \"commission\": 9.99, \"price\": 140.8, \"total\": 704.0, \"date\": \"2022-08-05\"})\n\tat org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl$1.handleException(EntityManagerSetupImpl.java:788)\n\tat
Googling led to this answer
https://stackoverflow.com/questions/38466095/in-a-was-liberty-connection-pool-can-i-validate-connections-on-borrow
So the connection pool should be:
<connectionManager id="dbConnections" maxPoolSize="50" purgePolicy="ValidateAllConnections" validationTimeout="10m"/>
I've been running this for 2 months now without seeing any more concurrent delete errors in portfolio.
In an effort to consolidate secrets (IBMStockTrader/trade-history#36), some bindings should be updated to be compatible with Service Broker generated secrets.
The following bindings need to be changed:
api-key
-> apikey
address
-> url
Topic and Consumer Group ID are not included in the generated secret from Service Broker, and are currently being stored in a manually created kafka-extra
secret.
kafka:topic
-> kafka-extra:topic
When using IBM EventStreams/Kafka the authentication mechanism is via username/password using the PLAIN
SASL Mechanism. This can be partially seen in EventStreamsProducer.java
:
...
properties.put(SaslConfigs.SASL_MECHANISM, "PLAIN");
properties.put(SaslConfigs.SASL_JAAS_CONFIG, "org.apache.kafka.common.security.plain.PlainLoginModule required username=\"" + USERNAME + "\" password=\"" + API_KEY + "\";");
...
However, Amazon MSK uses a different set of SASL mechanisms as outlined below:
...
properties.put(SaslConfigs.SASL_MECHANISM, "SCRAM-SHA-512");
properties.put(SaslConfigs.SASL_JAAS_CONFIG, "org.apache.kafka.common.security.scram.ScramLoginModule required username=\"" + USERNAME + "\" password=\"" + API_KEY + "\";");
...
Azure Event Hubs can make use of the same, PLAIN
, configuration or it can use OAUTHBEARER
tokens with callback.
We need a generic mechanism to specify the SASL configuration for Kafka.
The current stocktrader can connect to MQ which the MQ itself have no password configured for user app.
when trying to connecting to MQ which the MQ itself have a password configured for user app, it will be failed.
so, there might be a hardcoded/constrain "BLANK" password for MQ in app stocktrader
so, we better ether :
below is the MQ log when stocktrader connecting to a MQ which password setup for app user:
04/10/20 14:38:09 - Process(434.319) User(mqm) Program(amqrmppa)
Host(stocktrader-mq-ibm-mq-0) Installation(Installation1)
VRMF(9.1.5.0) QMgr(stocktradermq)
Time(2020-04-10T14:38:09.426Z)
RemoteHost(172.30.130.217)
CommentInsert1(jar)
CommentInsert2(172.30.130.217)
CommentInsert3(MCAUSER(app) CLNTUSER(default))
AMQ9791E: The client application did not supply a user ID and password.
EXPLANATION:
The client application 'jar' running on host '172.30.130.217' did not supply a
user ID and password. The channel authentication (CHLAUTH) record for the
connection requires a user ID and password, but none was supplied.
The active values of the channel were 'MCAUSER(app) CLNTUSER(default)'. The
MATCH(RUNCHECK) mode of the DISPLAY CHLAUTH MQSC command can be used to
identify the relevant CHLAUTH record.
ACTION:
Ensure that the application provides a valid user ID and password, or change
the queue manager connection authority (CONNAUTH) configuration to OPTIONAL to
allow client applications to connect which have not supplied a user ID and
password.
If Event Stream is deployed on ICP, service name should be used to access service stream. For example:
kubectl create secret generic kafka -n stock-trader --from-literal=topic=stocktrader --from-literal=address=event-streams-trader-ibm-es-proxy-svc.event-streams.svc.cluster.local:30001 --from-literal=user=token --from-literal=api-key=
Stock Trader portfolio service works great in ICP.
However, when we port it to IKS, the Watson service does not get called.
[INFO ] Error from Watson
[WARNING ] javax.ws.rs.WebApplicationException: HTTP 400 Bad Request
[INFO ] javax.ws.rs.WebApplicationException: HTTP 400 Bad Request```
```{“message”: “Error communicating with the Watson Tone Analyzer”, “free”: 0, “sentiment”: “Unknown”}```
Here's what we know:
- Works fine in ICP
- Tried multiple Tone Analyzer services but no luck
- We confirmed the failure on other IKS instances, so it's not limited to our instance.
Currently static certs.jks is used for Event Stream, however, it has to be replaced with own event stream topic certs.jks. Please provide alternate way to replace certs.jks.
Normal behavior if a create request fails due to a conflict (already existing portfolio for id) would be to return http 409
The default
key in the supplied key.jks
expired at the start of October.
Alias name: default
Creation date: Oct 1, 2017
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=localhost, OU=StockTrader, O=ibm, C=us
Issuer: CN=localhost, OU=StockTrader, O=ibm, C=us
Serial number: 5da80e03
Valid from: Sun Oct 01 17:53:22 EDT 2017 until: Mon Oct 01 17:53:22 EDT 2018
As a starting suggestion,
And leave the main app where it is.
Any sort of hierarchical grouping will vastly help people understand the codebase
If the PUT call is for a stock not currently held by the identified portfolio, and the stock level specified is negative. The insert will succeed and store a negative quantity of stock.
Handling for negative amounts is never really clear, it should probably result in an error, and the request being rejected entirely if a request drives a stock to negative levels, as it would imply the portfolio was not in the state the user expected. (eg, tring to remove 2000 shares from a holding of 20 should result in silently dropping the 20 shares as a 'success' it should be an error that the other 1980 requested removals were not possible, and thus the request was aborted)
INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.493s
[INFO] Finished at: Mon Apr 02 22:54:43 EDT 2018
[INFO] Final Memory: 12M/130M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal on project portfolio: Could not resolve dependencies for project com.stocktrader:portfolio:war:1.0-SNAPSHOT: The following artifacts could not be resolved: net.wasdev.wlp.starters.ms-builder:config:jar:0.1, net.wasdev.wlp.starters.ms-builder:faulttolerance:jar:0.1: Failure to find net.wasdev.wlp.starters.ms-builder:config:jar:0.1 in http://liberty-app-accelerator.wasdev.developer.ibm.com/start/api/v1/repo was cached in the local repository, resolution will not be reattempted until the update interval of liberty-starter-maven-repo has elapsed or updates are forced -> [Help 1]
Watson has moved over to iam/apikey based auth.
Newly deployed Watson services do not offer Userid/Password based credentials, only apikey instead.
Current portfolio implementation does not support this, so it is no longer possible to deploy new instances of StockTrader.
When the steps above are recreated, the error message below generates. I'm currently unsure of what this would affect
Portfolio's log:
Launching defaultServer (Open Liberty 22.0.0.12/wlp-1.0.71.cl221220221107-1900) on Eclipse OpenJ9 VM, version 17.0.5+8 (en_US)
[AUDIT ] CWWKE0001I: The server defaultServer has been launched.
[AUDIT ] CWWKG0093A: Processing configuration drop-ins resource: /opt/ol/wlp/usr/servers/defaultServer/configDropins/defaults/keystore.xml
[AUDIT ] CWWKG0093A: Processing configuration drop-ins resource: /opt/ol/wlp/usr/servers/defaultServer/configDropins/defaults/open-default-port.xml
[AUDIT ] CWWKG0028A: Processing included configuration resource: /opt/ol/wlp/usr/servers/defaultServer/includes/postgres.xml
[INFO ] CWWKE0002I: The kernel started after 6.603 seconds
[INFO ] CWWKF0007I: Feature update started.
[INFO ] CWWKS0007I: The security service is starting...
[AUDIT ] CWWKZ0058I: Monitoring dropins for applications.
[INFO ] DYNA1001I: WebSphere Dynamic Cache instance named baseCache initialized successfully.
[INFO ] DYNA1071I: The cache provider default is being used.
[INFO ] DYNA1056I: Dynamic Cache (object cache) initialized successfully.
[INFO ] CWWKS5780I: The MicroProfile JWT version 1.2 mpConfigProxy processed successfully.
[INFO ] CWWKS4103I: Creating the LTPA keys. This may take a few seconds.
[INFO ] CWWKS1123I: The collective authentication plugin with class name NullCollectiveAuthenticationPlugin has been activated.
[INFO ] CWPKI0830I: Certificate with the CN=IBM Cloud Databases SubjectDN from the cert_defaultTrustStore environment variable is being added to the defaultTrustStore keystore.
[INFO ] CWPKI0830I: Certificate with the CN=Amazon RDS Root 2019 CA,OU=Amazon RDS,O=Amazon Web Services\, Inc.,ST=Washington,L=Seattle,C=US SubjectDN from the cert_defaultTrustStore environment variable is being added to the defaultTrustStore keystore.
[INFO ] CWPKI0830I: Certificate with the CN=Amazon RDS us-east-1 2019 CA,OU=Amazon RDS,O=Amazon Web Services\, Inc.,L=Seattle,ST=Washington,C=US SubjectDN from the cert_defaultTrustStore environment variable is being added to the defaultTrustStore keystore.
[INFO ] CWPKI0830I: Certificate with the L=Seattle,CN=Amazon RDS us-east-1 Root CA RSA2048 G1,ST=WA,OU=Amazon RDS,O=Amazon Web Services\, Inc.,C=US SubjectDN from the cert_defaultTrustStore environment variable is being added to the defaultTrustStore keystore.
[INFO ] CWPKI0830I: Certificate with the L=Seattle,CN=Amazon RDS us-east-1 Root CA RSA4096 G1,ST=WA,OU=Amazon RDS,O=Amazon Web Services\, Inc.,C=US SubjectDN from the cert_defaultTrustStore environment variable is being added to the defaultTrustStore keystore.
[INFO ] CWPKI0830I: Certificate with the L=Seattle,CN=Amazon RDS us-east-1 Root CA ECC384 G1,ST=WA,OU=Amazon RDS,O=Amazon Web Services\, Inc.,C=US SubjectDN from the cert_defaultTrustStore environment variable is being added to the defaultTrustStore keystore.
[INFO ] CWWKS1655I: The default Java Authentication SPI for Containers (JASPIC) AuthConfigFactory class com.ibm.ws.security.jaspi.ProviderRegistry is being used because the Java security property authconfigprovider.factory is not set.
[INFO ] Successfully loaded default keystore: /opt/ol/wlp/usr/servers/defaultServer/resources/security/key.p12 of type: pkcs12
[AUDIT ] CWWKS4104A: LTPA keys created in 3.198 seconds. LTPA key file: /opt/ol/wlp/output/defaultServer/resources/security/ltpa.keys
[INFO ] CWWKS4105I: LTPA configuration is ready after 3.324 seconds.
[INFO ] CWWKS6012I: The JSON Web Token (JWT) consumer service is available.
[INFO ] CWWKS6002I: The JSON Web Token (JWT) endpoint service is available.
[INFO ] CWWKS5500I: The MicroProfile JWT configuration [MicroProfileJwtService] was successfully processed.
[INFO ] CWWKS5500I: The MicroProfile JWT configuration [defaultMpJwt] was successfully processed.
[INFO ] CWWKS5500I: The MicroProfile JWT configuration [stockTraderJWT] was successfully processed.
[INFO ] SESN8501I: The session manager did not find a persistent storage location; HttpSession objects will be stored in the local application server's memory.
[INFO ] CWPMI2003I: Monitoring metrics can be retrieved through mpMetrics.
[INFO ] SRVE0169I: Loading Web Module: health.
[INFO ] SRVE0250I: Web Module health has been bound to default_host.
[AUDIT ] CWWKT0016I: Web application available (default_host): http://cjot-portfolio-864555bc-7hdzq:9080/health/
[INFO ] SRVE0169I: Loading Web Module: ibm/api.
[INFO ] SRVE0250I: Web Module ibm/api has been bound to default_host.
[AUDIT ] CWWKT0016I: Web application available (default_host): http://cjot-portfolio-864555bc-7hdzq:9080/ibm/api/
[INFO ] SRVE0169I: Loading Web Module: IBMJMXConnectorREST.
[INFO ] SRVE0250I: Web Module IBMJMXConnectorREST has been bound to default_host.
[AUDIT ] CWWKT0016I: Web application available (default_host): http://cjot-portfolio-864555bc-7hdzq:9080/IBMJMXConnectorREST/
[INFO ] CWWKX0103I: The JMX REST connector is running and is available at the following service URL: service:jmx:rest://cjot-portfolio-864555bc-7hdzq:9443/IBMJMXConnectorREST
[INFO ] CWWKX0103I: The JMX REST connector is running and is available at the following service URL: service:jmx:rest://cjot-portfolio-864555bc-7hdzq:9443/IBMJMXConnectorREST
[INFO ] SRVE0169I: Loading Web Module: PublicMicroProfileMetrics.
[INFO ] SRVE0250I: Web Module PublicMicroProfileMetrics has been bound to default_host.
[AUDIT ] CWWKT0016I: Web application available (default_host): http://cjot-portfolio-864555bc-7hdzq:9080/metrics/
[INFO ] SRVE0169I: Loading Web Module: OpenAPIUI.
[INFO ] SRVE0250I: Web Module OpenAPIUI has been bound to default_host.
[AUDIT ] CWWKT0016I: Web application available (default_host): http://cjot-portfolio-864555bc-7hdzq:9080/openapi/ui/
[INFO ] SRVE0169I: Loading Web Module: com.ibm.ws.security.jwt.
[INFO ] SRVE0250I: Web Module com.ibm.ws.security.jwt has been bound to default_host.
[AUDIT ] CWWKT0016I: Web application available (default_host): http://cjot-portfolio-864555bc-7hdzq:9080/jwt/
[INFO ] CWWKZ0018I: Starting application Portfolio.
[INFO ] CWWKZ0136I: The Portfolio application is using the archive file at the /opt/ol/wlp/usr/servers/defaultServer/apps/Portfolio.war location.
[INFO ] SRVE0169I: Loading Web Module: /openapi/platform.
[INFO ] SRVE0250I: Web Module /openapi/platform has been bound to default_host.
[AUDIT ] CWWKT0016I: Web application available (default_host): http://cjot-portfolio-864555bc-7hdzq:9080/openapi/platform/
[INFO ] SRVE0169I: Loading Web Module: MicroProfileOpenAPI.
[INFO ] SRVE0250I: Web Module MicroProfileOpenAPI has been bound to default_host.
[AUDIT ] CWWKT0016I: Web application available (default_host): http://cjot-portfolio-864555bc-7hdzq:9080/openapi/
[INFO ] SESN0176I: A new session context will be created for application key default_host/ibm/api
[INFO ] SESN0176I: A new session context will be created for application key default_host/health
[INFO ] SESN0172I: The session manager is using the Java default SecureRandom implementation for session ID generation.
[INFO ] SESN0172I: The session manager is using the Java default SecureRandom implementation for session ID generation.
[INFO ] DYNA1056I: Dynamic Cache (object cache) initialized successfully.
[INFO ] SRVE0242I: [io.openliberty.microprofile.health.3.1.internal] [/health] [HealthCheckReadinessServlet]: Initialization successful.
[INFO ] SRVE0242I: [io.openliberty.microprofile.health.3.1.internal] [/health] [HealthCheckServlet]: Initialization successful.
[INFO ] SRVE0242I: [io.openliberty.microprofile.health.3.1.internal] [/health] [HealthCheckStartupServlet]: Initialization successful.
[INFO ] SRVE0242I: [io.openliberty.microprofile.health.3.1.internal] [/health] [HealthCheckLivenessServlet]: Initialization successful.
[INFO ] SESN0176I: A new session context will be created for application key default_host/IBMJMXConnectorREST
[INFO ] SESN0172I: The session manager is using the Java default SecureRandom implementation for session ID generation.
[INFO ] SRVE0242I: [com.ibm.ws.jmx.connector.server.rest] [/IBMJMXConnectorREST] [JMXRESTProxyServlet]: Initialization successful.
[INFO ] SESN0176I: A new session context will be created for application key default_host/metrics
[INFO ] SESN0172I: The session manager is using the Java default SecureRandom implementation for session ID generation.
[INFO ] SRVE0242I: [io.openliberty.microprofile.metrics.internal.public] [/metrics] [PublicMetricsRESTProxyServlet]: Initialization successful.
[INFO ] SRVE9103I: A configuration file for a web server plugin was automatically generated for this server at /opt/ol/wlp/output/defaultServer/logs/state/plugin-cfg.xml.
[INFO ] SESN0176I: A new session context will be created for application key default_host/openapi/ui
[INFO ] SESN0172I: The session manager is using the Java default SecureRandom implementation for session ID generation.
[INFO ] SESN0176I: A new session context will be created for application key default_host/openapi/platform
[INFO ] SESN0172I: The session manager is using the Java default SecureRandom implementation for session ID generation.
[INFO ] SESN0176I: A new session context will be created for application key default_host/jwt
[INFO ] SESN0172I: The session manager is using the Java default SecureRandom implementation for session ID generation.
[INFO ] SESN0176I: A new session context will be created for application key default_host/openapi
[INFO ] SESN0172I: The session manager is using the Java default SecureRandom implementation for session ID generation.
[INFO ] SRVE0242I: [io.openliberty.microprofile.openapi.2.0.internal] [/openapi] [ApplicationServlet]: Initialization successful.
[INFO ] J2CA8050I: An authentication alias should be used instead of defining a user name and password on dataSource[PortfolioDB].
[INFO ] CWRLS0010I: Performing recovery processing for local WebSphere server (defaultServer).
[INFO ] CWRLS0007I: No existing recovery log files found in /opt/ol/wlp/output/defaultServer/tranlog/tranlog. Cold starting the recovery log.
[INFO ] CWRLS0006I: Creating new recovery log file /opt/ol/wlp/output/defaultServer/tranlog/tranlog/log1.
[INFO ] CWRLS0006I: Creating new recovery log file /opt/ol/wlp/output/defaultServer/tranlog/tranlog/log2.
[INFO ] CWRLS0007I: No existing recovery log files found in /opt/ol/wlp/output/defaultServer/tranlog/partnerlog. Cold starting the recovery log.
[INFO ] CWRLS0006I: Creating new recovery log file /opt/ol/wlp/output/defaultServer/tranlog/partnerlog/log1.
[INFO ] CWRLS0006I: Creating new recovery log file /opt/ol/wlp/output/defaultServer/tranlog/partnerlog/log2.
[INFO ] CWRLS0012I: All persistent services have been directed to perform recovery processing for this WebSphere server (defaultServer).
[INFO ] WTRN0135I: Transaction service recovering no transactions.
[WARNING ] You have specified multiple ids for the entity class [com.ibm.hybrid.cloud.sample.stocktrader.portfolio.json.Stock] without specifying an @IdClass. By doing this you may lose the ability to find by identity, distributed cache support etc. Note: You may however use EntityManager find operations by passing a list of primary key fields. Else, you will have to use JPQL queries to read your entities. For other id options see @PrimaryKey.
[INFO ] CWWKO1660I: The application Portfolio was processed and an OpenAPI document was produced.
[INFO ] WELD-000900: 3.1.9 (Final)
[INFO ] CWWKO0219I: TCP Channel defaultHttpEndpoint has been started and is now listening for requests on host * (IPv6) port 9080.
[INFO ] CWWKO0219I: TCP Channel defaultHttpEndpoint-ssl has been started and is now listening for requests on host * (IPv6) port 9443.
[AUDIT ] CWWKF0012I: The server installed the following features: [json-1.0, jwt-1.0, microProfile-4.1, monitor-1.0, mpConfig-2.0, mpFaultTolerance-3.0, mpHealth-3.1, mpJwt-1.2, mpMetrics-3.0, mpOpenAPI-2.0, mpOpenTracing-2.0, mpRestClient-2.0, opentracing-2.0, restConnector-2.0].
[AUDIT ] CWWKF0013I: The server removed the following features: [appClientSupport-1.0, batch-1.0, beanValidation-2.0, concurrent-1.0, ejb-3.2, ejbHome-3.2, ejbLite-3.2, ejbPersistentTimer-3.2, ejbRemote-3.2, j2eeManagement-1.1, jacc-1.5, jaspic-1.1, javaMail-1.6, javaee-8.0, jaxb-2.2, jaxws-2.2, jca-1.7, jcaInboundSecurity-1.0, jms-2.0, jsf-2.3, jsp-2.3, managedBeans-1.0, mdb-3.2, wasJmsClient-2.0, wasJmsSecurity-1.0, wasJmsServer-1.0, webProfile-8.0, websocket-1.1].
[INFO ] CWWKF0008I: Feature update completed in 49.792 seconds.
[AUDIT ] CWWKF0011I: The defaultServer server is ready to run a smarter planet. The defaultServer server started in 56.313 seconds.
[AUDIT ] CWWKZ0022W: Application Portfolio has not started in 30.318 seconds.
[INFO ] Publishing to Trade History topic enabled: false
[INFO ] Cash Account microservice enabled: false
[INFO ] Using Stock Quote URL from config map: http://cjot-stock-quote-service:9080/stock-quote
[INFO ] CWWKW0750I: The following interfaces are configured as RequestScoped which will result in slower performance: Consider using ApplicationScoped for better performance.
[INFO ] SRVE0169I: Loading Web Module: Portfolio.
[INFO ] SRVE0250I: Web Module Portfolio has been bound to default_host.
[AUDIT ] CWWKT0016I: Web application available (default_host): http://cjot-portfolio-864555bc-7hdzq:9080/portfolio/
[INFO ] SESN0176I: A new session context will be created for application key default_host/portfolio
[INFO ] SESN0172I: The session manager is using the Java default SecureRandom implementation for session ID generation.
[AUDIT ] CWWKZ0001I: Application Portfolio started in 31.589 seconds.
[INFO ] CWWKS9123I: For URL /* in application Portfolio, the following HTTP methods are uncovered, and not accessible: HEAD OPTIONS TRACE
[INFO ] SRVE9103I: A configuration file for a web server plugin was automatically generated for this server at /opt/ol/wlp/output/defaultServer/logs/state/plugin-cfg.xml.
[INFO ] Setting the server's publish address to be /
[INFO ] SRVE0242I: [Portfolio] [/portfolio] [com.ibm.hybrid.cloud.sample.stocktrader.portfolio.PortfolioService]: Initialization successful.
[err] SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
[err] SLF4J: Defaulting to no-operation (NOP) logger implementation
[err] SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
[INFO ] CWMOT1001I: A JaegerTracer instance was created for the Portfolio application. Tracing information is sent to localhost:6831.
[INFO ] EclipseLink, version: Eclipse Persistence Services - 2.7.11.v20220804-52dea2a3c0
[INFO ] DSRA8203I: Database product name : PostgreSQL
[INFO ] DSRA8204I: Database product version : 12.12
[INFO ] DSRA8205I: JDBC driver name : PostgreSQL JDBC Driver
[INFO ] DSRA8206I: JDBC driver version : 42.5.3
[WARNING ]
Internal Exception: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "stock_pkey"
Detail: Key (owner, symbol)=(Testing, KD) already exists.
Error Code: 0
Call: INSERT INTO STOCK (SYMBOL, COMMISSION, dateQuoted, PRICE, SHARES, TOTAL, owner) VALUES (?, ?, ?, ?, ?, ?, ?)
bind => [7 parameters bound]
Query: InsertObjectQuery({"symbol": "KD", "shares": 10, "commission": 0.0, "price": 0.0, "total": 0.0, "date": "null"})
[WARNING ] Failure refreshing portfolio for Testing
[WARNING ] javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.11.v20220804-52dea2a3c0): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "stock_pkey"
Detail: Key (owner, symbol)=(Testing, KD) already exists.
Error Code: 0
Call: INSERT INTO STOCK (SYMBOL, COMMISSION, dateQuoted, PRICE, SHARES, TOTAL, owner) VALUES (?, ?, ?, ?, ?, ?, ?)
bind => [7 parameters bound]
Query: InsertObjectQuery({"symbol": "KD", "shares": 10, "commission": 0.0, "price": 0.0, "total": 0.0, "date": "null"})
[INFO ] javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.11.v20220804-52dea2a3c0): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "stock_pkey"
Detail: Key (owner, symbol)=(Testing, KD) already exists.
Error Code: 0
Call: INSERT INTO STOCK (SYMBOL, COMMISSION, dateQuoted, PRICE, SHARES, TOTAL, owner) VALUES (?, ?, ?, ?, ?, ?, ?)
bind => [7 parameters bound]
Query: InsertObjectQuery({"symbol": "KD", "shares": 10, "commission": 0.0, "price": 0.0, "total": 0.0, "date": "null"})
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:980)
at org.eclipse.persistence.internal.jpa.QueryImpl.performPreQueryFlush(QueryImpl.java:978)
at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:211)
at org.eclipse.persistence.internal.jpa.QueryImpl.getResultList(QueryImpl.java:482)
at com.ibm.hybrid.cloud.sample.stocktrader.portfolio.dao.StockDao.readStockByOwner(StockDao.java:56)
at com.ibm.hybrid.cloud.sample.stocktrader.portfolio.dao.StockDao$Proxy$_$$_WeldClientProxy.readStockByOwner(Unknown Source)
at com.ibm.hybrid.cloud.sample.stocktrader.portfolio.PortfolioService.getPortfolio(PortfolioService.java:255)
at com.ibm.hybrid.cloud.sample.stocktrader.portfolio.PortfolioService$Proxy$_$$_WeldSubclass.getPortfolio(Unknown Source)
at com.ibm.hybrid.cloud.sample.stocktrader.portfolio.PortfolioService.updatePortfolio(PortfolioService.java:420)
at com.ibm.hybrid.cloud.sample.stocktrader.portfolio.PortfolioService$Proxy$_$$_WeldSubclass.updatePortfolio$$super(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.jboss.weld.interceptor.proxy.TerminalAroundInvokeInvocationContext.proceedInternal(TerminalAroundInvokeInvocationContext.java:51)
at org.jboss.weld.interceptor.proxy.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:78)
at com.ibm.tx.jta.cdi.interceptors.TransactionalInterceptor$1.run(TransactionalInterceptor.java:137)
at com.ibm.ws.uow.embeddable.EmbeddableUOWManagerImpl.runUnderCurrentUOW(EmbeddableUOWManagerImpl.java:1077)
at com.ibm.ws.uow.embeddable.EmbeddableUOWManagerImpl.runUnderNewUOW(EmbeddableUOWManagerImpl.java:1040)
at com.ibm.ws.uow.embeddable.EmbeddableUOWManagerImpl.runUnderUOW(EmbeddableUOWManagerImpl.java:1013)
at com.ibm.tx.jta.cdi.interceptors.TransactionalInterceptor.runUnderUOWManagingEnablement(TransactionalInterceptor.java:151)
at com.ibm.tx.jta.cdi.interceptors.Required.required(Required.java:40)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.jboss.weld.interceptor.reader.SimpleInterceptorInvocation$SimpleMethodInvocation.invoke(SimpleInterceptorInvocation.java:73)
at org.jboss.weld.interceptor.proxy.InterceptorMethodHandler.executeAroundInvoke(InterceptorMethodHandler.java:84)
at org.jboss.weld.interceptor.proxy.InterceptorMethodHandler.executeInterception(InterceptorMethodHandler.java:72)
at org.jboss.weld.interceptor.proxy.InterceptorMethodHandler.invoke(InterceptorMethodHandler.java:56)
at org.jboss.weld.bean.proxy.CombinedInterceptorAndDecoratorStackMethodHandler.invoke(CombinedInterceptorAndDecoratorStackMethodHandler.java:79)
at org.jboss.weld.bean.proxy.CombinedInterceptorAndDecoratorStackMethodHandler.invoke(CombinedInterceptorAndDecoratorStackMethodHandler.java:68)
at com.ibm.hybrid.cloud.sample.stocktrader.portfolio.PortfolioService$Proxy$_$$_WeldSubclass.updatePortfolio(Unknown Source)
at com.ibm.hybrid.cloud.sample.stocktrader.portfolio.PortfolioService$Proxy$_$$_WeldClientProxy.updatePortfolio(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at com.ibm.ws.jaxrs20.cdi.component.JaxRsFactoryImplicitBeanCDICustomizer.serviceInvoke(JaxRsFactoryImplicitBeanCDICustomizer.java:350)
at com.ibm.ws.jaxrs20.server.LibertyJaxRsServerFactoryBean.performInvocation(LibertyJaxRsServerFactoryBean.java:641)
at com.ibm.ws.jaxrs20.server.LibertyJaxRsInvoker.performInvocation(LibertyJaxRsInvoker.java:160)
at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:101)
at com.ibm.ws.jaxrs20.server.LibertyJaxRsInvoker.invoke(LibertyJaxRsInvoker.java:273)
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:213)
at com.ibm.ws.jaxrs20.server.LibertyJaxRsInvoker.invoke(LibertyJaxRsInvoker.java:444)
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:112)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:59)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:96)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:123)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:277)
at com.ibm.ws.jaxrs20.endpoint.AbstractJaxRsWebEndpoint.invoke(AbstractJaxRsWebEndpoint.java:137)
at com.ibm.websphere.jaxrs.server.IBMRestServlet.handleRequest(IBMRestServlet.java:146)
at com.ibm.websphere.jaxrs.server.IBMRestServlet.doPut(IBMRestServlet.java:136)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
at com.ibm.websphere.jaxrs.server.IBMRestServlet.service(IBMRestServlet.java:96)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1258)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:746)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:443)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.invokeTarget(WebAppFilterChain.java:193)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:98)
at com.ibm.ws.security.jaspi.JaspiServletFilter.doFilter(JaspiServletFilter.java:56)
at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:201)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:91)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:1002)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1140)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1011)
at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:75)
at com.ibm.ws.webcontainer40.servlet.CacheServletWrapper40.handleRequest(CacheServletWrapper40.java:85)
at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:938)
at com.ibm.ws.webcontainer.osgi.DynamicVirtualHost$2.run(DynamicVirtualHost.java:281)
at com.ibm.ws.http.dispatcher.internal.channel.HttpDispatcherLink$TaskWrapper.run(HttpDispatcherLink.java:1246)
at com.ibm.ws.http.dispatcher.internal.channel.HttpDispatcherLink.wrapHandlerAndExecute(HttpDispatcherLink.java:468)
at com.ibm.ws.http.dispatcher.internal.channel.HttpDispatcherLink.ready(HttpDispatcherLink.java:427)
at com.ibm.ws.http.channel.internal.inbound.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:567)
at com.ibm.ws.http.channel.internal.inbound.HttpInboundLink.handleNewRequest(HttpInboundLink.java:501)
at com.ibm.ws.http.channel.internal.inbound.HttpInboundLink.processRequest(HttpInboundLink.java:361)
at com.ibm.ws.http.channel.internal.inbound.HttpInboundLink.ready(HttpInboundLink.java:328)
at com.ibm.ws.tcpchannel.internal.NewConnectionInitialReadCallback.sendToDiscriminators(NewConnectionInitialReadCallback.java:167)
at com.ibm.ws.tcpchannel.internal.NewConnectionInitialReadCallback.complete(NewConnectionInitialReadCallback.java:75)
at com.ibm.ws.tcpchannel.internal.WorkQueueManager.requestComplete(WorkQueueManager.java:514)
at com.ibm.ws.tcpchannel.internal.WorkQueueManager.attemptIO(WorkQueueManager.java:584)
at com.ibm.ws.tcpchannel.internal.WorkQueueManager.workerRun(WorkQueueManager.java:968)
at com.ibm.ws.tcpchannel.internal.WorkQueueManager$Worker.run(WorkQueueManager.java:1057)
at com.ibm.ws.threading.internal.ExecutorServiceImpl$RunnableWrapper.run(ExecutorServiceImpl.java:245)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:857)
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.11.v20220804-52dea2a3c0): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "stock_pkey"
Detail: Key (owner, symbol)=(Testing, KD) already exists.
Error Code: 0
Call: INSERT INTO STOCK (SYMBOL, COMMISSION, dateQuoted, PRICE, SHARES, TOTAL, owner) VALUES (?, ?, ?, ?, ?, ?, ?)
bind => [7 parameters bound]
Query: InsertObjectQuery({"symbol": "KD", "shares": 10, "commission": 0.0, "price": 0.0, "total": 0.0, "date": "null"})
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:342)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.processExceptionForCommError(DatabaseAccessor.java:1666)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:915)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:979)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:640)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:567)
at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:2105)
at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:313)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:275)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:261)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:428)
at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:168)
at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:183)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:515)
at org.eclipse.persistence.queries.InsertObjectQuery.executeCommit(InsertObjectQuery.java:85)
at org.eclipse.persistence.queries.InsertObjectQuery.executeCommitWithChangeSet(InsertObjectQuery.java:95)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:327)
at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:60)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:913)
at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:812)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:110)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:87)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:3004)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1898)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1880)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1830)
at org.eclipse.persistence.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(CommitManager.java:229)
at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:128)
at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:4409)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1503)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithPreBuiltChangeSet(UnitOfWorkImpl.java:1649)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.writeChanges(RepeatableWriteUnitOfWork.java:457)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:975)
... 87 more
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "stock_pkey"
Detail: Key (owner, symbol)=(Testing, KD) already exists.
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2676)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2366)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:356)
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:496)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:413)
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:190)
at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:152)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.postgresql.ds.PGPooledConnection$StatementHandler.invoke(PGPooledConnection.java:441)
at jdk.proxy31/jdk.proxy31.$Proxy128.executeUpdate(Unknown Source)
at com.ibm.ws.rsadapter.jdbc.WSJdbcPreparedStatement.executeUpdate(WSJdbcPreparedStatement.java:520)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:907)
... 117 more
There should be a separation of keystore and truststore
Keystore is for private keys, used for signing stuff, or hosting https endpoints.
Truststore is for verifying stuff, jwts, or connecting to https endpoints.
Truststore should never contain private keys.
Portfolio probably only needs to be using a Truststore to validate JWTs with a public key. (And to trust the outbound calls for watson etc).
Uncomment properties.put(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, ""); in EventStreamsProducer.java
In trying to utilize using Kafka with IBM Event Stream, I think it is best to ensure that Kafka is able to connect properly with an event stream to avoid data going out of sync (between portfolio and the event stream).
This may add some overhead work to make sure secrets are setup properly.
The same should be done on any consumers to ensure that they only consume when they are able to correctly process/store the consumed events.
Usually the logs look like this:
log:[WARNING ] Failure sending message to Kafka
log:[WARNING ] java.util.concurrent.ExecutionException: org.apache.kafka.common.errors.SslAuthenticationException: SSL handshake failed
log: Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
Hi John,
Please consider externalize these two host names and port through a secret object.
The current implementation of portfolio uses a config map entry from kafka.historyTopic
which is mapped to the environment variable KAFKA_HISTORY_TOPIC
to determine which Kafka topic to forward trade history to. In the current implementation the topic is decided by KAFKA_TOPIC
which is not currently used which means we use the default topic, stocktrader
.
Let's update portfolio to use KAFKA_HISTORY_TOPIC
.
Two binary jars included in this project are NOT apache2 licensed, and should not be distributed as such.
Idea is to define a POJO with an @Entity
annotation with a getter/setter for each column, per table (Portfolio
and Stock
). Then PortfolioService.java
would just call those accessor methods on the appropriate POJO to persist/retrieve data to/from the JDBC database (such as DB2).
Right now I'm doing things the way you would have 20 years ago - time to move up to something more modern (and to make the code a bit more similar to the Spring version).
There's a pretty good example here: http://www.vogella.com/tutorials/JavaPersistenceAPI/article.html
When setting the database to be Postgres and SSL flag to false, it appears to still try the SSL handshake.
See below for a reference code snippet and error output from portfolio logs:
database:
kind: postgres
db: postgres
host: x.x.x.x
id: postgres
password: !@#$%^
port: 5432
ssl: false
SSL HANDSHAKE FAILURE: A signer with SubjectDN [C=US, O="Google, Inc", CN=xyz] was sent from the host [35.239.229.155:5432]. The signer might need to be added to local trust store [/opt/ol/wlp/usr/servers/defaultServer/resources/security/trust.p12], located in SSL configuration alias [defaultSSLConfig]. The extended error message from the SSL handshake exception is: [PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target].
CWPKI0828E: The trustDefaultCerts attribute is enabled but trust was not established by using the default truststore. The extended error message from the SSL handshake exception is: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target.
[11/15/21, 19:55:57:348 UTC] 00000025 aultServer/apps/Portfolio.war!/WEB-INF/classes/_jpa-unit.ejb E
Local Exception Stack:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.9.v20210604-2c549e2208): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: SSL error: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target DSRA0010E: SQL State = 08006, Error Code = 0
Originally ALL headers were cloned from the source request to the outbound request to StockQuote, (via copyFromRequest
now only the JWT header is being passed on (as an arg to mpRestClient).
Please confirm/document the expected behavior, so other implementations know what is expected.
Cloning all headers might seem excessive, but it would allow for trace span headers to propagate, so wouldn't be entirely unexpected for this kind of onward propagation.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.