0

I come across a situation where I need to put a code block that is needed only for unit tests or QA, and it must not be present for production. This must be implemented so that the code is maintainable and readable. I am thinking about this and below is one approach, but I need help to finalize it...

Develop the class ServiceClient which needs to invoke a REST Service with SSL. The service needs to initiate SSLContext and on the UAT environment, we need to add this code block to be executed only in the test environment:

package com.uat.environment;
public class ServiceClient extends com.prod.environment.ServiceClient {
...
...
    static {
        //for localhost testing only
        javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(newJavaKeyword javax.net.ssl.HostnameVerifier() {
            public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
                if (hostname.equals("localhost")) {
                    return true;
                }
                return false;
            }
        });
    }
...
...
}

Note: replace the keyword above newJavaKeyword with new as it won't let me post it using new for some reason.

The above code block will disable matching the hostname for localhost with the self-signed certificate owner/issuer CN=Tom Akehurst for WireMock.

The correct version of the class ServiceClient intended for the production environment will be developed in the package com.prod.environment as follows without the static code block above:

package com.prod.environment;
public class ServiceClient {
...
...
  public void ServiceClient() {
    ...
    ...
  }
...
...
}

Then, will ensure to configure maven pom.xml to generate two jar files service_uat.jar and service_prod.jar. That is, one will have the UAT package, and the other will have the production package. When running the program using java.exe' I want to configure the classpathso that if the UAT jar file is present in the classpath, then when the client code references the class nameServiceClassit will pick the UAT version. And, if I don't add the UAT jar and only add the prod jar to the classpath, then the client code will pick theServiceClass` from the prod package.

The client code will be something like the following:

import com.prod.environment.ServiceClass;
import com.uat.environment.ServiceClass;

public static void main() {
  ...
  ServiceClass service = new ServiceClass();
  ...
}

What I want to happen is that if the UAT jar is present, it should pick the UAT version, if not, it will pick the prod version.

I am not sure how to achieve this objective... I think the compiler will report an error if I try to import the same class name from two different packages.

What is the appropriate way to achieve this?


Update:

I am thinking about this ... maybe we can introduce a factory class called ServiceClientFactory. This class will be responsible for referencing/creating the correct version of the ServiceClient class and triggering the static block. The ServiceClientFactory will check if the package com.uat.environment is present and then reference the class using com.uat.environment.ServiceClient, if not present then reference the prod version com.prod.environment.ServiceClient.

I am nor sure how to do that and appreciate your help.

tarekahf
  • 738
  • 1
  • 16
  • 42
  • Cannot you put both UAT and PROD jar files in your class path with UAT jar ahead of the Prod jar? – user9035826 Aug 01 '23 at 05:04
  • That's why I'm asking this question! Can you share your answer with some details? – tarekahf Aug 01 '23 at 05:06
  • java -cp "......:uat.jar:prod.jar:...." MyMainClass – user9035826 Aug 01 '23 at 05:10
  • But how to resolve the class reference? Are you saying I should specify the same package qualified name for both classes? I can't create the package twice unless it's in a separate project and doesn't look a good idea! I'm not sure if I'm following you correctly! – tarekahf Aug 01 '23 at 05:15
  • Java searches for a class in the jar files in the same order as they are specified in the class path. Once it finds one, it will stop. So, it doesn't matter if a class is defined more than once. Yes, they need to have the same package names. You may also need to have two projects. I have seen this kind of techniques widely used in very large java projects. – user9035826 Aug 01 '23 at 05:23
  • If your project is small, and you don't feel like to split it, you can also specify your service "provider" classes in a configure file. You will run the UAT class if it exists. Otherwise, run the production one. – user9035826 Aug 01 '23 at 05:54
  • @CjY sorry, I don't follow you. Please provide more details. I don't know how to configure service provided. – tarekahf Aug 01 '23 at 15:36
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/254751/discussion-between-tarekahf-and-cj-y). – tarekahf Aug 01 '23 at 15:37

0 Answers0