Some code may be reused in various environments including Java EE Application server. Sometimes it is nice to know whether the code is running under application server and which application server is it.
I prefer to do it by checking some system property typical for the application server.
For example it may be
jboss.server.name for JBoss
catalina.base for Tomcat
Does somebody know appropriate property name for other servers?
Weblogic, Websphere, Oracle IAS, others?
It is very easy to check if you have the specific application server installed. Just add line
System.getProperties() to any JSP, Servlet, EJB and print the result.
I can do it myself but it will take a lot of time to install server and make it working.
I have read this discussion: How to determine type of Application Server an application is running on?
But I prefer to use system property. It is easier and absolutely portable solution. The code does not depend on any other API like Servlet, EJBContext or JMX.
JBoss AS sets a lot of diffrent system properties:
jboss.home.dir
jboss.server.name
You can check other properties using for example VisualVM or other tools.
I don't know other servers but I think you can find some kind of properties for each of them.
This is not a 'standard' way but what I did was to try to load a Class of the AppServer.
For WAS:
try{
Class cl = Thread.getContextClassLoader().loadClass("com.ibm.websphere.runtime.ServerName");
// found
}
// not Found
catch(Throwable)
{
}
// For Tomcat: "org.apache.catalina.xxx"
Etc.
Let me know what you think
//for Tomcat
try {
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("Catalina", "type", "Server");
StandardServer server = (StandardServer) mBeanServer.getAttribute(name,"managedResource");
if (server != null) {
//its a TOMCAT application server
}
} catch (Exception e) {
//its not a TOMCAT Application server
}
//for wildfly
try {
ObjectName http = new ObjectName("jboss.as:socket-binding-group=standard-sockets,socket- binding=http");
String jbossHttpAddress = (String) mBeanServer.getAttribute(http, "boundAddress");
int jbossHttpPort = (Integer) mBeanServer.getAttribute(http, "boundPort");
String url = jbossHttpAddress + ":" + jbossHttpPort;
if(jbossHttpAddress != null){
//its a JBOSS/WILDFLY Application server
}
} catch (Exception e) {
//its not a JBOSS/WILDFLY Application server
}
Related
I am trying to connect to an external weblogic embeded LDAP in Oracle ADF.
I've just found a good sample code that uses JpsContextFactory class, it doesnt get any url, username and password. it seems that it connects to local weblogic ldap by defult. I could not figure out how to set a connection to an external weblogic ldap using this class.
the sample code :
private void initIdStoreFactory() {
JpsContextFactory ctxFactory;
try {
ctxFactory = JpsContextFactory.getContextFactory();
JpsContext ctx = ctxFactory.getContext();
LdapIdentityStore idStoreService = (LdapIdentityStore) ctx.getServiceInstance(IdentityStoreService.class);
ldapFactory = idStoreService.getIdmFactory();
storeEnv.put(OIDIdentityStoreFactory.RT_USER_SEARCH_BASES, USER_BASES);
storeEnv.put(OIDIdentityStoreFactory.RT_GROUP_SEARCH_BASES, GROUP_BASES);
storeEnv.put(OIDIdentityStoreFactory.RT_USER_CREATE_BASES, USER_BASES);
storeEnv.put(OIDIdentityStoreFactory.RT_GROUP_CREATE_BASES, GROUP_BASES);
storeEnv.put(OIDIdentityStoreFactory.RT_GROUP_SELECTED_CREATE_BASE, GROUP_BASES[0]);
storeEnv.put(OIDIdentityStoreFactory.RT_USER_SELECTED_CREATE_BASE, USER_BASES[0]);
} catch (JpsException e) {
e.printStackTrace();
throw new RuntimeException("Jps Exception encountered", e);
}
}
any suggestion how to use this code to connect to external ldap will be appreciated.
JpsContextFactory is utilised to retrieve the current information of the identity store(s) inside weblogic. In order to use it with an external LDAP, you need first to add a new security provider in Weblogic and declare it as required in order for your application to utilise the new external ldap.
Check this old article of how to do it (http://www.itbuzzpress.com/weblogic-tutorials/securing-oracle-weblogic/configuring-oracle-weblogic-security-providers.html)
I am using the Restlet Framework, but now I want to change to a proper server instead of using localhost.
I have already added my php files (they access the java files using the rest_server URL) to the server's folder and my java files as well, but I am not sure how to change the code so it identifies where the new location of the files is.
Here is the code from IdentiscopeServer (constructor empty):
public static void main(String[] args) throws Exception {
//setsup our security manager
if (System.getSecurityManager() == null){
System.setSecurityManager(new SecurityManager());
}
identiscopeServerApp = new IdentiscopeServerApplication();
IdentiscopeServer server = new IdentiscopeServer();
server.getServers().add(Protocol.HTTP,8888);
server.getDefaultHost().attach("", identiscopeServerApp);
server.start();
}
I guess that the correct line to change is the one with "Protocol.HTTP, 8888". If the address of my new server is http://devweb2013.co.uk/research/Identiscope, how exactly do I set this up? Is there anything else necessary for it to work apart from just moving the files to a folder in the server?
The IdensticopeServerApplication is the following:
public class IdentiscopeServerApplication extends Application {
public IdentiscopeServerApplication() {
}
public Restlet createInboundRoot() {
Router router = new Router(getContext());
//attaches the /tweet path to the TweetRest class
router.attach("/collectionPublic", CollectionPublicREST.class);
router.attach("/collectionPrivate", CollectionPrivateREST.class);
router.attach("/analysis", AnalysisREST.class);
return router;
}
}
Thank you in advance, it is my first time using this Framework.
If I understand you correctly, you just want to run your main() method as the server, correct? In this case, the code for main() needs to be in a location that -- when running -- can provide the service at http://devweb2013.co.uk/research/Identiscope. Since you haven't stated what kind of server you are putting the code, I can't say where the best place to put the code would be. I assume you have superuser privileges on your deployment server, since the URL you provided implies port 80 will be serving your Identiscope web service (port 80 is a privileged port on most OS's). So as an answer, I can only provide general information.
On your deployment server, port 80 must be free (i.e. nothing else should be acting as a web server on port 80 on that machine) and the IdentiscopeApplication must be running on port 80. To do that, you need only change the line:
server.getServers().add(Protocol.HTTP,8888);
to:
server.getServers().add(Protocol.HTTP, 80);
then run the application as a user that is allowed to start servers on port 80 (preferably NOT the superuser). If you haven't already, you will need to get Java running on your deployment server and make sure all Restlet libraries are in the classpath where you plan to run your application.
If I understand what you are trying to do, then this should do the trick.
Is it possible to set environment variables at the application level in websphere?
Websphere servers can host multiple applications. Any environment variable applied at the server level applies to all the applications on that server. Is it possible to create variables that only apply to individual applications?
For example:
Lets say we have a SpreadsheetApp and a DocsApp running on the same server. They both share some common code that can be configured via an environment variable called DocStorageLocation. Is it possible to set the DocStorageLocation differently for both applications?
Alternatively, is there another way of configuring multiple applications running on the same server?
QUESTION 1
Is it possible to set the DocStorageLocation differently for both
applications?
I don't think it is possible. Websphere's environment variables are meant to be used by the server itself. A variable has only three possible scopes, which are Server, Cluster and Node.
For instance, an ORACLE_JDBC_DRIVER_PATH environment variable on server1, node1 scope could be used for the JDBC provider on node1 (classPath = ${ORACLE_JDBC_DRIVER_PATH}/ojdbc14.jar).
The question is : "why can't I set a different value for my application only" ? But my guess is that as long as the server, clusters and nodes are started, it does not make sense to override this value for a deployed application.
Although I think it is not possible, I still tried. But I did not manage to override an environment variable set for the websphere server.
QUESTION 2
Alternatively, is there another way of configuring multiple
applications running on the same server?
Environment entry
You could add an environment entry to your web.xml deployment descriptor, a variable you can look up for.
<env-entry>
<env-entry-name>DocStorageLocation</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>C:/DocStorage</env-entry-value>
</env-entry>
Then test, look up for this variable in the java class :
//TEST
Object l_test = null;
try {
Context l_ctx = new InitialContext();
l_test = l_ctx.lookup("java:comp/env/DocStorageLocation");
} catch (NamingException e1) {
// TODO
e1.printStackTrace();
}
URL ressource for .properties file
You can create an URL ressource. It would link to a .properties file set on a local host or any server, so each property could be set to a different value depending on the environment.
For instance, JNDI name url/environmentJndiName with value file:///server1/environment.properties on server1, and file:///server2/environment.properties on server2.
Then on server 1, you could set docStorageLocation=value1 in the environment.properties file, docStorageLocation=value2 on server2.
In your deployment descriptor web.xml, the ressource's reference would be the same. You wouldn't have to change this reference in the java source :
<resource-ref>
<res-ref-name>url/environment</res-ref-name>
<res-type>java.net.URL</res-type>
<res-auth>Application</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
Then use this ressource to read the properties.
try {
Context l_ctx = new InitialContext();
URL l_url = (URL) l_ctx.lookup("java:comp/env/url/environment");
// New properties
Properties l_properties = new Properties();
// Load properties
this.loadProps(l_properties, l_url.getPath());
} catch (NamingException e1) {
// TODO
e1.printStackTrace();
} catch (IOException e) {
// TODO Bloc catch auto-généré
e.printStackTrace();
}
...
private void loadProps(final Properties p_properties, final String p_fileLocation)
throws IOException
{
// Open stream
BufferedInputStream l_is = new BufferedInputStream(
new FileInputStream(
new File(p_fileLocation)));
p_properties.load(l_is);
// Close stream
l_is.close();
}
You will need to bind the ressource reference url/environment of the web.xml to the JNDI name url/environmentJndiName set for this ressource on the websphere server. Modify the ibm-web-bnd.xml file with websphere, the sun-web.xml file with glassfish, etc.
THANKS
If there is a better solution, or if it does not answer the question, let me know. I am still learning but I have been working with websphere for a while - even if I prefer other solutions. Thanks, #+.
I have a desktop application built with jdk 6 which publishes web services to be consumed by a web application. So far I've had no problem while both applications are running in the same physical computer, i can access the wsdl without any problem and the web application works with the desktop application just fine. The thing is I cannot access to the services from a remote computer in the same network. The two PCs are connected and can interact. If I run both applications in PC1, from PC2 I can use the webapp through
http://PC1:8080
I am currently publishing like this:
public Publicador(){
servicios= new Servicios();
Endpoint endpoint = Endpoint.publish("http://PC1:8686/servicios", servicios);
}
where PC1 is the name of the pc. From PC1, i can see the generated wsdl from the following address, and it's the one I used for the wsimport command:
http://PC1:8686/servicios?wsdl
But I cannnot from PC2.
Any ideas why it is not visible from outside PC1?
Incredible as it may seem, I found the simplest of answers... Instead of publishing as
Endpoint endpoint = Endpoint.publish("http://PC1:8686/servicios", servicios);
I published as
Endpoint endpoint = Endpoint.publish("http://0.0.0.0:8686/servicios", servicios);
and that solved it...
Another solution was to get the address to publish from a file, that worked too. I don't know why it didn't hardcoded... I ended up doing it like this:
Properties prop = new Properties();
InputStream is = null;
String currenDir = System.getProperty("user.dir");
String nombreArchivo = currenDir + File.separator + "ubicacion.PROPERTIES";
try {
is=new FileInputStream(nombreArchivo);
prop.load(is);
} catch(IOException ioe) {}
String pc = prop.getProperty("ServiciosWeb");
Endpoint endpoint = Endpoint.publish( pc, servicios);
}
I am trying to write a client utility that to connect to Tomcat via JMX and look at the status of the connection datasource.
I set the following VM arguments in $CATALINA_HOME/bin/setenv.bat and restarted Tomcat
set JAVA_OPTS=-Xms512M -Xmx1024M -XX:MaxPermSize=256M %JAVA_OPTS%
set CATALINA_OPTS=-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9004 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false %CATALINA_OPTS%
I am not very familiar with JMX so i am just having a play with it to get the feel of it.
The utility i am writing will be running outside of Tomcat. I wrote the following test to try and access datasource Mbean object in Tomcat
but for some reason it is not finding it.
public class GuiMonitor {
public static void main(String[] args){
try{
JMXServiceURL url = new JMXServiceURL(
"service:jmx:rmi:///jndi/rmi://localhost:9004/jmxrmi");
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
final List<MBeanServer> servers = new LinkedList<MBeanServer>();
servers.add(ManagementFactory.getPlatformMBeanServer());
servers.addAll(MBeanServerFactory.findMBeanServer(null));
System.out.println("MbeanServers " + servers.size());
for(final MBeanServer server : servers){
System.out.println("Server : " + server.getClass().getName());
}
MBeanServer mbsc = ManagementFactory.getPlatformMBeanServer();
System.out.println(mbsc.queryMBeans(null, null));
ObjectName on = new ObjectName("Catalina:type=DataSource,path=/appdb,host=localhost,class=javax.sql.DataSource,name=\"jdbc/appdb\"");
System.out.println("ObjectName : " + on.toString());
System.out.println(mbsc.getAttribute(on, "Catalina:type=DataSource,path=/appdb,host=localhost,class=javax.sql.DataSource,name=\"jdbc/appdb\""));
} catch (Exception e) {
e.printStackTrace();
}
}
}
I have a JSP page that i found on the internet which when i upload onto the webapps folder and run it, it displays all of the available
MBeans in Tomcat. The object string/name i used above came from the name that was reported on both the jsp page i used and Jconsole so it does exist.
The output to the above program is shown below
MbeanServers 2
Server : com.sun.jmx.mbeanserver.JmxMBeanServer
Server : com.sun.jmx.mbeanserver.JmxMBeanServer
[com.sun.management.OperatingSystem[java.lang:type=OperatingSystem], sun.management.MemoryPoolImpl[java.lang:type=MemoryPool,name=Tenured Gen], sun.management.MemoryPoolImpl[java.lang:type=MemoryPool,name=Perm Gen], java.util.logging.Logging[java.util.logging:type=Logging], sun.management.CompilationImpl[java.lang:type=Compilation], javax.management.MBeanServerDelegate[JMImplementation:type=MBeanServerDelegate], sun.management.MemoryImpl[java.lang:type=Memory], sun.management.MemoryPoolImpl[java.lang:type=MemoryPool,name=Survivor Space], sun.management.RuntimeImpl[java.lang:type=Runtime], sun.management.GarbageCollectorImpl[java.lang:type=GarbageCollector,name=Copy], sun.management.MemoryPoolImpl[java.lang:type=MemoryPool,name=Eden Space], sun.management.GarbageCollectorImpl[java.lang:type=GarbageCollector,name=MarkSweepCompact], sun.management.ThreadImpl[java.lang:type=Threading], sun.management.MemoryPoolImpl[java.lang:type=MemoryPool,name=Perm Gen [shared-ro]], sun.management.MemoryPoolImpl[java.lang:type=MemoryPool,name=Perm Gen [shared-rw]], sun.management.HotSpotDiagnostic[com.sun.management:type=HotSpotDiagnostic], sun.management.ClassLoadingImpl[java.lang:type=ClassLoading], sun.management.MemoryManagerImpl[java.lang:type=MemoryManager,name=CodeCacheManager], sun.management.MemoryPoolImpl[java.lang:type=MemoryPool,name=Code Cache]]
ObjectName : Catalina:type=DataSource,path=/appdb,host=localhost,class=javax.sql.DataSource,name="jdbc/appdb"
javax.management.InstanceNotFoundException: Catalina:type=DataSource,path=/appdb,host=localhost,class=javax.sql.DataSource,name="jdbc/appdb"
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getMBean(DefaultMBeanServerInterceptor.java:1094)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getAttribute(DefaultMBeanServerInterceptor.java:662)
at com.sun.jmx.mbeanserver.JmxMBeanServer.getAttribute(JmxMBeanServer.java:638)
at com.bt.c21.c21mon.C21GuiMonitor.main(C21GuiMonitor.java:39)
A couple of questions
Is the URL correct? I know the port number is correct but i am not sure of the service name. The service name "jmxrmi" i am using on the URL is just one that i saw in one of the examples i have been looking at.
I have a feeling that this is connecting to a different MBeanServer. I suspect this because if you look at the output of mbsc.queryMBeans(null, null), there is nothing tomcat specific. What service name do i use for the Tomcat instance?
If the URL is correct then is the service name always jmxrmi? And why does it not find the "Catalina:type=DataSource,path=/appdb,host=localhost,class=javax.sql.DataSource,name=\"jdbc/appdb\"" entry?
I have seen a lot of examples of how to do this and most use a different method to get teh MbeanServer. A couple of examples i have seen are
ManagementFactory.getPlatformMBeanServer()
MBeanServerFactory.findMBeanServer(null)
getMBeanServerConnection()
As mentioned earlier, the utility i am writing is a normal java application that will be running outside of tomcat. Is there any other configuration that i have missed out? I have been looking at several examples and the majority talk about creating MBeans and there is usually references to Listeners. As i am not creating any new Mbeans but only reading the values of existing ones, do i need to configure a listener?
Edit
It seems that getPlatformMbeanServer() is not returning the correct JVM Instance. I tried the following
MBeanServerConnection conn = jmxc.getMBeanServerConnection();
System.out.println("Query2 : " + conn.queryMBeans(null, null));
And this does return some Tomcat specific values. But i am still unable to get the jdbc/appdb datasource.
krtek - I wont be able to use JMX Console as i plan to do it all manually with the intention of automating it.
Edit 2
Ok, i figured out what i was doing wrong. Initially i was trying to retrieve the values as
MBeanServerConnection conn = jmxc.getMBeanServerConnection();
ObjectName on = new ObjectName("Catalina:type=DataSource,path=/appdb,host=localhost,class=javax.sql.DataSource,name=\"jdbc/appdb\"");
mbsc.getAttribute(on, "Catalina:type=DataSource,path=/appdb,host=localhost,class=javax.sql.DataSource,name=\"jdbc/appdb\""));
The above is wrong because the second parameter for mbsc.getAttribute is supposed to be the attribute in the Mbean not the String name.
This gave me the correct attribute values
MBeanServerConnection conn = jmxc.getMBeanServerConnection();
ObjectName on = new ObjectName("Catalina:type=DataSource,path=/appdb,host=localhost,class=javax.sql.DataSource,name=\"jdbc/appdb\"");
mbsc.getAttribute(on, "numIdle")
And i also changed the MBeanServer i was using from getPlatformMbeanServer() to getMBeanserverConnection(). I must admit i dont quite understand the difference because since Tomcat is running on the same JVM as the one returned by getPlatformMbeanServer(). Does it mean that getPlatformMbeanServer() will only return sun specific Mbeans? and getMBeanserverConnection() will include both?
Thanks
That's because you are getting instance of JMX server for your client JVM, not the Tomcat one.
This is right:
JMXServiceURL url = new JMXServiceURL(
"service:jmx:rmi:///jndi/rmi://localhost:9004/jmxrmi");
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
But you should continue with something like:
MBeanServerConnection conn = jmxc.getMBeanServerConnection();
Set result = conn.queryMBeans(null,
"Catalina:type=DataSource,path=/appdb,host=localhost,class=javax.sql.DataSource");
To test your query string use some tool like JMX console.