• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Liutauras Vilda
  • Jeanne Boyarsky
  • paul wheaton
Sheriffs:
  • Ron McLeod
  • Devaka Cooray
  • Henry Wong
Saloon Keepers:
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Tim Moores
  • Mikalai Zaikin
Bartenders:
  • Frits Walraven

Issue running a compiled JAR file locally

 
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello,

I've the following Java code in my component in which I need to access an IBM MQ using SSL/certificate.
The required keyStore file(MyKStoreFile.pfx) is present under "src/main/resources" folder in my Java project.



1. When I run this code in IntelliJ IDE, it works fine and am able to connect to the queue and send messages.
2. When the above code is sent to Jenkins for compilation and then pushed to cloud server using Harnes/CloudFoundry, it is working fine as well.
3. But when I run the compiled JAR file(using java -jar myJar.jar) locally on my windows machine, I get an error on line #1 above, saying:
"class path resource[MyKStoreFile.pfx] cannot be resolved to absolute file path because it does not reside in the file system."

Can you please explain this behaviour? Why does it work on the server and not when I manually run the compiled JAR locally?
And how do I make this work?

Thank you for your help!
 
Sheriff
Posts: 28323
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
When you run a jar file that way, the Java classpath only includes folders which are inside the jar. I don't know how your ResourceUtils class works but if it uses the Java classpath then you need to put your MyKStoreFile.pfx file inside the jar when you create the jar. And you have to put it in the right folder in the jar, which I'm not sure what that might be.

The name of the folder itself would be "resources", it's pretty clear, but it probably wouldn't be "/src/main/resources". My most likely guess is "/main/resources" but have a look at how your classpath is actually set up in IntelliJ. It looks like the process to export to the cloud already understands this issue and puts the pfx file into the correct place, so you might be able to reverse-engineer that and see what it's doing.
 
Saloon Keeper
Posts: 28319
210
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The key phrase here is "does not reside in the filesystem".

"Files" and "directories" inside a JAR are not files in the strict sense. They are resources.

The difference is that you cannot use standard OS API calls - or Java I/O APIs that invoke them - to open/close/read/write/update/delete the "files" inside the JAR. Those resources have to be accessed using Java's resource methods such as "getResourceAsStream()".

Additionally, you cannot create/write/update/delete a resource from a JAR. The only way that can be done is to create a new, updated copy of the JAR.

The reason why some of your platforms "work" is because they are not actually interacting with the JAR file, but with its contents in "exploded" (unzipped) form. That can happen in an IDE when you use the IDE to run and it uses the original or intermediate build product files, or on a server if the server explodes when the JAR is deployed. For example, by default WARs deployed to the Tomcat webapp server will be exploded when the WAR is deployed. Though good practice means that you should not code apps assuming that expectation.
 
Bartender
Posts: 303
12
IntelliJ IDE Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I feel like an alternate approach is what you'd really want here... without relying on external filesystem access at all. Assuming you need to bundle a keystore inside the jar.

In some environments (cloud etc.) I'd say it's reasonable to rely on resources outside of your jar, and that's probably even preferable for update convenience and security reasons. Would you be okay with redeploying your jar if your keystore (or truststore) need an update? If not, you want them external to the jar and deployed separately anyway.

I'm not familiar with IBM MQ, but if you're keeping things inside the jar, what you could likely do here is setup an SSL context/connection programatically. A quick search found something called "MQConnectionFactory" which seems relevant, but again I've never used this product. Provide a connection factory (which probably needs a keystore/truststore... takes a bit of code), and you could load whatever you need straight out of your jar as an InputStream. Been some years since I've done anything similar, but it's doable.
 
Tim Holloway
Saloon Keeper
Posts: 28319
210
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Lou Hamers wrote:
I'm not familiar with IBM MQ, but if you're keeping things inside the jar, what you could likely do here is setup an SSL context/connection programatically. A quick search found something called "MQConnectionFactory" which seems relevant, but again I've never used this product. Provide a connection factory (which probably needs a keystore/truststore... takes a bit of code), and you could load whatever you need straight out of your jar as an InputStream. Been some years since I've done anything similar, but it's doable.



It's a bit stickier than that.

A keystore is a database which typically chains several certs to form a "chain of trust". InputStreams are sequential, and thus incapable of the required key/data lookups (further complicated by the fact that both the keystore and its entries are separately encrypted).

About the best you could do with an in-jar keystore is to open it as an inputstream and copy the whole thing to an external file, then use the external copy.

That said, MQ should be handling the encryption itself in most cases, and thus have its own keystore outside of the JAR, as it's also supposed to be handling the incoming messages including their transport and listener port (default is port 1414).

Note that I am assuming that we're actually talking about the literal MQ server. IBM in their infinite marketing wisdom has conflated WebSphere and MQ to the  point where we might actually need to be talking about the WebSphere MQ webapp server. Which, again, has its own keystore and handles TLS/SSL directly, when not fronted by a less perilous reverse proxy server like Apache or nginx. As always, it's extremely risky for ANY java application server to listen on a port number less than 4096, which means that a JEE web server is better fronted by a reverse proxy and a messaging server should not be connected to the open Internet, only the LAN.
 
Lou Hamers
Bartender
Posts: 303
12
IntelliJ IDE Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:
It's a bit stickier than that.



This is what I meant (caveat - low effort example). You don't think this would work?

 
Lou Hamers
Bartender
Posts: 303
12
IntelliJ IDE Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I feel like I had to do something like this once with a JFX uberjar application. Although it was probably with a truststore with a special root cert, rather than a keystore.
 
Tim Holloway
Saloon Keeper
Posts: 28319
210
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Normally, you'd use a keystore when you're an SSL server, not an SSL client. The certificate chain for Java TLS clients is located within the JAVA_HOME directory tree. Details on how to add third-party certs to that are something I'd have to refresh my memory on.
 
Sheriff
Posts: 4641
582
VSCode Eclipse IDE TypeScript Redhat MicroProfile Quarkus Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

mitu kumarsgp wrote:Can you please explain this behaviour? Why does it work on the server and not when I manually run the compiled JAR locally?
And how do I make this work?


Your post on StackOverflow had a comment to see the post: Classpath resource not found when running as jar.  Did that provide any help?
 
Tim Holloway
Saloon Keeper
Posts: 28319
210
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Ron McLeod wrote:

mitu kumarsgp wrote:Can you please explain this behaviour? Why does it work on the server and not when I manually run the compiled JAR locally?
And how do I make this work?


Your post on StackOverflow had a comment to see the post: Classpath resource not found when running as jar.  Did that provide any help?


It basically says the same thing I did.
 
Lou Hamers
Bartender
Posts: 303
12
IntelliJ IDE Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:Normally, you'd use a keystore when you're an SSL server, not an SSL client. The certificate chain for Java TLS clients is located within the JAVA_HOME directory tree. Details on how to add third-party certs to that are something I'd have to refresh my memory on.



Code like I put above, definitely not a typical use case. I think we agree that you typically want this stuff external to your jar and I wouldn't advocate deviating unless you need to.

I had to teach myself this stuff in depth up to two-way SSL. A lot more fun when you get to the point where you understand it, but it takes time that most of us don't want to spend. And it's amazing how eagerly the knowledge wants to evaporate once you learn it. I had a decent understanding years ago, now I need to sit and think about it.
 
There were millions of the little blood suckers. But thanks to this tiny ad, I wasn't bitten once.
Gift giving made easy with the permaculture playing cards
https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
reply
    Bookmark Topic Watch Topic
  • New Topic