Is there any guideline on how to use EPICOR’s swagger framework in Java?
I am facing one problem the generated swagger objects from EPICOR restful library are missing a few authorization objects.
For example, I have no way to pass the authorization without modified the ApiClient class:
[INFO] Running io.swagger.client.api.TestApi
java.lang.RuntimeException: No API key authentication configured!
at io.swagger.client.ApiClient.setApiKey(ApiClient.java:309)
at io.swagger.client.api.TestApi.RESTFullConnectionTest(TestApi.java:63)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.apache.maven.surefire.junitcore.pc.Scheduler$1.run(Scheduler.java:398)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:750)
After I add the following to constructor:
HttpBasicAuth hba = new HttpBasicAuth();
hba.setUsername(appConfig.getApiuser());
hba.setPassword(appConfig.getApipwd());
authentications.put("basicAuth", hba);
ApiKeyAuth auth = new ApiKeyAuth(appConfig.getKeystore(), "X-API-KEY");
auth.setApiKey(appConfig.getApikey());
auth.setApiKeyPrefix("x-api-key");
authentications.put("apiKey", auth);
// Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications);
I have another error:
io.swagger.client.ApiException: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at io.swagger.client.ApiClient.execute(ApiClient.java:872)
at io.swagger.client.api.ODataApi.getListWithHttpInfo(ODataApi.java:6112)
at io.swagger.client.api.ODataApi.getList(ODataApi.java:6091)
That’s why I want to ask if there is any official guideline from EPICOR I can look it how to put my integration working
It is on-prem environment. We don’t have a signed cert for the testing environment yet. However, from a typical REST test (like postman), I don’t have any issues.
I do have Java keystore preparation done. However, I can’t verify if it works or not.
Frome swagger generated by online tools (yaml → java POJO), I don’t find any method to let me add the basic authorization info for making the call. I modify the ApiClient.java constructor by adding the HttpBasicAuth and ApiKeyAuth so that it won’t throw exceptions while getting objects from the authentications map object.
==================== ApiClient.java constructor I modified for test =================
authentications = new HashMap<String, Authentication>();
// SENTEC Specific Authentication objects
HttpBasicAuth hba = new HttpBasicAuth();
hba.setUsername(appConfig.getApiuser());
hba.setPassword(appConfig.getApipwd());
authentications.put("basicAuth", hba);
ApiKeyAuth auth = new ApiKeyAuth(appConfig.getKeystore(), "X-API-KEY");
auth.setApiKey(appConfig.getApikey());
auth.setApiKeyPrefix("x-api-key");
authentications.put("apiKey", auth);
// Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications);
Sure. In this case however, we do know that self-signed certs only work if all the communication is on the same machine. That is why a Visual Studio dev cert always works for local development. But the moment we try to communicate outside our machine, we’re wasting a crap-ton of time trying to work around it. We know the definition of insanity afterall.
And I’m not suggesting that my solution is the best or only one. It fulfilled my requirement for automation with the new cert lifetimes shrinking. I bet @EarlGrei has some clever tricks up his sleeve that makes this easier too. If we want to pain to stop, having a real cert should be the best practice in normal land. No?
Using Certify paired with a supported EXTERNAL DNS Host, like Cloudflare (what we use), you do not have to even bother exposing the service to the internet to get the SSL certificates to validate. We only have 1 server that is exposed to the internet on ANY ports but we have several that run Certify for various purposes. ALL are getting Lets Encrypt valid certificates for our domain.
I am certainly not either. I have my workflow, others have theirs.
I try to promote balance in how I work, but I also have a lifetime of
dealing with ADHD to lean on. I’ve learned the hard lessons on what
I deal with today vs tomorrow.
It should.
I’m only saying, IF you have the discipline, choose what works best for you in the situation.
If you do not, always color between the lines.
I have areas of my life where I must stay between the lines, because I’ve either learned a hard lesson, or it’s more important to do it right the first time.