cancel
Showing results for 
Search instead for 
Did you mean: 

SAP JC0 3.1.7 - Getting destination inside thread. Losing Context

sub_han
Employee
Employee
0 Kudos

The following does not work when i am inside a new thread in Java.

JCoDestinationManager.getDestination("_________")


Context:
The Java application is a springboot application deployed in BTP. It uses the connectivity and destination Service.
It works perfectly fine if I call the above method outside a new thread.
When I create a new thread ( in my case, it is the `ExecutorService` in Java), I get the following

com.sap.conn.jco.JCoException: (106) JCO_ERROR_RESOURCE: Destination _______ does not exist


I am also doing the following to have the security context propagated in the new thread:

SecurityContext context= SecurityContextHolder.getContext();
DelegatingSecurityContextRunnable wrappedRunnable = 
                     new DelegatingSecurityContextRunnable(operation, context);


Here `operation` is a runnable where i call `JCoDestinationManager.getDestination`


Can anybody please guide here what I have to do?

I am even manually setting the security context inside the thread.

Here is the code:

import com.sap.cloud.security.spring.token.SpringSecurityContext;
import com.sap.cloud.security.token.SecurityContext;
import java.util.concurrent.ExecutorService;


private ExecutorService executorService;

...

Token token = SpringSecurityContext.getToken();
JCoDestinationManager.getDestination("_________") //THIS WORKS
final Runnable runnable = () ->{
SecurityContext.setToken(token);
JCoDestinationManager.getDestination("_________"); //THIS DOES NOT WORK }

SecurityContext context= SecurityContextHolder.getContext(); DelegatingSecurityContextRunnable wrappedRunnable = new DelegatingSecurityContextRunnable(runnable, context);

executorService.submit(wrappedRunnable);
HAL9000
Product and Topic Expert
Product and Topic Expert
0 Kudos

This is not an answer. Please use "Add a Comment" instead.

HAL9000
Product and Topic Expert
Product and Topic Expert
0 Kudos

This is not an answer. Please use "Add a Comment" instead

HAL9000
Product and Topic Expert
Product and Topic Expert
0 Kudos

Just for the record:
"JCO" is spelled JCo and there is also no JCo version 3.1.72.

Accepted Solutions (1)

Accepted Solutions (1)

MarkusTolksdorf
Product and Topic Expert
Product and Topic Expert

Hi Subhan,

also make sure to not include the security libraries in your application, but use provided scope to avoid packaging of it. Otherwise, JCo cannot see tokens as the ThreadLocalStorage instance is also dependent on the class loader in use, i..e. JCo looks for the tokens in the ThreadLocalStorage loaded by the libraries class loader and the your code will store it in the ThreadLocalStorage instance loaded by the application class loader

Best regards,
Markus

sub_han
Employee
Employee
0 Kudos

Just leaving my findings here for others if they need it:

So they key to this was to understand that JCO only uses com.sap.cloud.security:java-api to get the token and set the token.

I am using com.sap.cloud.security.xsuaa:xsuaa-spring-boot-starter for authentication and jwt handling.
So naturally I was only using the following to get the token:

 Token token = SpringSecurityContext.getToken();

But Jco does not care about springSecurityContext which is just a wrapper for org.springframework.security.core.context.SecurityContextHolder


But only the following works for jco:

 com.sap.cloud.security.token.Token token = com.sap.cloud.security.token.SecurityContext.getToken(); 
com.sap.cloud.security.token.SecurityContext.setToken(token);
com.sap.cloud.security.token is inside the com.sap.cloud.security:java-api library.
And setting this library's scope as provided solves it the problem.
MarkusTolksdorf
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi Subham,

This is indeed correct, this should be clearly mentioned in the documentation. We do not use spring libraries in JCo embedding as JCo needs to run in arbitrary application contexts. Hence, we use the standard SAP security libraries for token handling. We will discuss internally how to improve the documentation

Best regards,
Markus

Mukesh_123
Associate
Associate
0 Kudos

Hi Subham,

Could you please explain little bit more about this below point.

com.sap.cloud.security.token is inside the com.sap.cloud.security:java-api library. And setting this library's scope as provided solves it the problem.

Thanks, Mukesh Mishra

Answers (2)

Answers (2)

simon_luser
Advisor
Advisor

The idea to set it again in the new thread is correct, as described here. However, I don't know how these spring related classes work, I assume that somehow the token is not properly propagated there. Are you using the newest lib versions and able to debug into this thread to investigate if the token is actually present in the SecurityContext?

sub_han
Employee
Employee
0 Kudos

I debugged and the tokens outside and inside the threadare the same. (correct zoneid)

Token token = SpringSecurityContext.getToken(); // SAME RESULT AS INSIDE the THREAD

System.out.println(SecurityContext.getToken()) //
JCoDestinationManager.getDestination("_________") //THIS WORKS final Runnable runnable = () ->{
System.out.println(SecurityContext.getToken()) //SAME RESULT AS OUTSIDE the THREAD
SecurityContext.setToken(token); JCoDestinationManager.getDestination("_________"); //THIS DOES NOT WORK }

I forgot to mention that this app is a multitenant application.
The app is deployed in Subaccount ID: A (provider subaccount) and the request to it comes from a subscriber in Subaccount ID: B (subscriber subaccount).

Both subaccounts A and B are in separate global accounts.

Outside the thread, JCO connects successfully to subaccount ID: B (correct behavior).
Inside the thread, JCO seems to be trying to connect via the cloud connector to Subaccount ID: A

FYI: The app is compiled for Java11 since jco can only support till Java11. And the app is deployed using sap_java_buildpack:1.74.0

I use the security dependencies mentioned here: https://github.com/SAP/cloud-security-services-integration-library/tree/main/spring-security

If i don't use a new thread, everything works seemlessly.


My dependencies are the following: (i highlighted the ones that are security deps)

(making them <socpe>provided</scope> does not work as the app crashes since the applicatiom loader can not find tjem)
Do you know which security dependencies to use?
Because according to the docs JCO uses:

<groupId>com.sap.cloud.security</groupId>
<artifactId>java-api</artifactId>
<dependencies>
		<dependency>
			<groupId>org.jooq</groupId>
			<artifactId>jooq</artifactId>
			<version>3.16.12</version>
		</dependency>
		<dependency>
			<groupId>org.flywaydb</groupId>
			<artifactId>flyway-core</artifactId>
			<version>9.21.1</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-validation</artifactId>
			<version>2.7.14</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
			<version>2.7.7</version>
		</dependency>
		<dependency>
			<groupId>com.nimbusds</groupId>
			<artifactId>nimbus-jose-jwt</artifactId>
			<version>9.31</version>
		</dependency>
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
			<version>4.5.14</version>
		</dependency>
		<dependency>
			<groupId>io.pivotal.cfenv</groupId>
			<artifactId>java-cfenv-boot</artifactId>
			<version>2.3.0</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>com.sap.cloud.db.jdbc</groupId>
			<artifactId>ngdbc</artifactId>
			<version>2.17.12</version>
		</dependency>

//START: SECURITY DEPENDENCIES
<dependency> <groupId>com.sap.cloud.security</groupId> <artifactId>resourceserver-security-spring-boot-starter</artifactId> <version>2.14.0</version>
// <scope>provided</scope> DOES NOT WORK WHEN DEPLOYED
</dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId>
// <scope>provided</scope> DOES NOT WORK WHEN DEPLOYED </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency>

//ENDOF: SECURITY DEPENDENCIES <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.sap.cloud</groupId> <artifactId>neo-java-web-api</artifactId> <version>4.46.5</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.8</version> <scope>compile</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> </dependencies>
simon_luser
Advisor
Advisor

As mentioned in the help site, please check the complete dependency tree and set only the mentioned one to provided:

Make sure you don't include this dependency


<dependency>
	<groupId>com.sap.cloud.security</groupId>
	<artifactId>java-security</artifactId>
</dependency>

or any of its dependencies such as java-api with scope compile directly or transitively with any other jar.

sub_han
Employee
Employee
0 Kudos

Thanks for the reply Simon.
And aplogies for not commenting in the correct way. I do not use this platform much.

Coming back to the topic:
I am not using com.sap.cloud.security:java-security as a dependency. But I solved my issue and explained it in the comment above.(reply to Markus)

I think JCO should have some documentation on how to use it along with Springboot.
There is a lot of confusion on how to use JCO with Springboot. What libraries to use and not to use.
Something that works for single-thread applications don't work for others just because of the scope of the library.
Apps without frameworks and plain Servlets are almost never used anymore in production.

If more EXAMPLES are created for this, it will be very helpful.


simon_luser
Advisor
Advisor
0 Kudos

thanks a lot for the feedback, we are going to discuss this internally.