1

Imagine we have a java package. This package can be used anywhere. However, there are some codes in this package which are context dependant. For instance, if the application which uses this package is a web app we need to perform some tasks by calling a function while performing other tasks if the application was a console application by calling the very same function.

Here is my question:

Is there any way in java that within the code we can detect if the application was run as a web app or a console? I appreciate any help :)

As a real world example, the ways we load properties files are different for web and console applications.

For web applications we probably use this.getClass().getClassLoader().getResourceAsStream(url) and for console apps we use new FileInputStream(physical path).

tecfield
  • 203
  • 2
  • 11

3 Answers3

2

It might be better to set a build property somewhere rather then trying to detect your application type, because I don't think there is a reliable way to do that.

Moreover you shouldn't try to detect application type because your view layer (either web, desktop or console) should be easily interchangeable according to modern architectural principles.


In response to your last comment.

As user384706 said DI is the correct choice here IMO. I will give an example with spring.

In both your console and web app parts you can have:

public class WebOrConsoleServiceImpl {

    private PropertyProvider propertyProvider = new NullPropertyProvider();

    // and

    public void setPropertyProvider(PropertyProvider impl) {
        this.propertyProvider = impl;
    }

    // and in your service logic

    public void logic() {

        final Properties props = propertyProvider.loadProperties();
        // do stuff            
    }
}

Where your loadProperties() method would be overriden for different implementations of your PropertyProvider.

And in your spring context you can have:

<bean id="consolePropertyProvider" class="com.company.ConsolePropertyProvider"/>

<bean id="myConsoleService" class="com.company.MyConsoleService">
    <property name="propertyProvider" ref="consolePropertyProvider" />
</bean>

And the same pair of bean definitions for your WebService and WebPropertyProvider.

Simeon
  • 7,582
  • 15
  • 64
  • 101
  • I wish to have the same code but it doesn't work. One example I brought up about loading properties is one of my problems. If I know the app type then I can put the proper code, otherwise I have no idea what to do :( – tecfield Sep 20 '11 at 20:35
  • can't you set a build property somewhere ? how do you build your project ? ant ? maven ? by hand ? in any case you should have some build file ? in that file you can add something like deployment.type=[web|console|desktop], and you change that value based on your deployment. This is the most reliable way to detect app type IMO. – Simeon Sep 20 '11 at 20:40
  • it's the same project. cannot do that! – tecfield Sep 20 '11 at 20:53
  • so you build it once for both deployments ? – Simeon Sep 20 '11 at 20:57
  • There are some web-parts (not sure if it is a good name) that we have designed to be used in our web application. There are some test cases and applications which use the same code and logic to perform some tasks - all these tasks and tests are running as console apps. We could have duplicated the code in order to have these both as separate projects but as you know, duplication just brings headache. On the other hand, we cannot add a build parameter because the web app is already done and in use (we cannot change its code to digest new settings). I wish there was an easy way like .NET! – tecfield Sep 21 '11 at 13:28
  • @tecfield if you can't change its code how were you planning to add the code that detects whether you're in a web or console application ? – Simeon Sep 21 '11 at 14:04
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/3663/discussion-between-simeon-and-tecfield) – Simeon Sep 21 '11 at 14:05
1

Just use dependency injection
Just place all the appropriate parameters to configure your library via setters and let the container or application configure it accordingly using DI.
So you will not need any checks which IMHO is a bad approach

Cratylus
  • 52,998
  • 69
  • 209
  • 339
  • to avoid hardcoding, I cannot do that. dependancy injection is good but if you don't need to change your settings often. – tecfield Sep 20 '11 at 20:47
0
  1. The J2EE way. If your package is used in a web application then, I am assuming that you are in a J2EE container then, you can add a Reference in the naming at deploy time. You can also register an MDB that can listen to the changes to this reference and modify behavior of your code at runtime. Sweet right?

  2. Other standard way in which you can pass the context of the caller is through a parametrized Factory or through properties.

  3. One non-standard way - for fun is to get the stack trace and look for who the caller is or look for j2ee context etc.

Community
  • 1
  • 1
RHT
  • 4,974
  • 3
  • 26
  • 32
  • will try #3. sounds doable but not sure if it is reliable :D thnx – tecfield Sep 20 '11 at 20:54
  • No. 3 is definitely not reliable because you do not know in advance who the caller might be but, it is certainly doable Call Thread.currentThread().getStackTrace() and then iterate through it. – RHT Sep 20 '11 at 21:11