How often do You face situation when local development is done using simple Tomcat or Jetty container? Very often backed up with JRebel? Yeah, that’s what I thought😉 It works like a charm but finally there is always an ultimate problem – deployment to dev/integration/prod environment. Why it is an issue? Because usually it is application server we have to deal with. And here comes the problem.
I’ve faced such situation many times. The expected truth is that it should make no difference. Servlet container is also a part of application server. Yes, I can agree to that, but very often there is some kind of a problem during application deployment in application server. If we have always-ready-to-fast-response-admin-team it is no such big deal. But what happens if reality is not so great – and the only thing we have is log file that does not tell us anything? We have a problem for sure. And that is exactly my point. It is better to understand a little bit of our application server. That is the subject of this blog post. I will show how to install and configure local instance of JBoss Wildfly and deploy simple application to it. I do not see this post as comprehensive tutorial – it is just some kind of ‘lessons learned’ to me. Let’s go.
Versioning, terminology and WTH is EAP?
In the good old days everything was simple. There was JBoss Application Server and that was it. I remember when I entered Java world version in use was 4.x one. As years went by I sometimes came across next versions of that server in my contractor’s career, but never paid special attention as I mostly used Weblogic. Some time ago I found out that there is some kind of new kid in town – Wildfly. After a little bit of digging I learned that it as good old Jboss AS but with different name. Why did that happen?
The answer is simple – JBoss Enterprise Application Platform (or for short Jboss EAP) emerged. EAP is a commercial product – it is usually much more ahead with bugfixes that community version of the server. To use it in a production mode you have to pay Jboss. On the other side there is still good old Jboss AS which is now called Wildfly mostly because there was very similar versioning of EAP and JBoss AS. The truth is – if You have EAP used in production (or dev/integration env) and You want to make sure Your app will work there use this site to find out which application’s server version You need and then download it and run. Wildfly is a name for newer version of Jboss AS (starting from version 8) and as far as I can see it, so far it is not yet used in EAP at all.
Despite what I have written above I decided to use latest stable Wildfly in my tutorial. Why? Because as I browsed through latest EAP and Wildfly documentation and folders I see no difference. What is more important – Wildfly can be downloaded ‘by hand’ from its page, with EAP registration is required. And I know for how many people that can be a concern😉 So just download 8.2.0.Final and we can start.
Installation, folder structure and first run
Installing JBoss is fairly easy – just download ZIP archive and unpack it. Piece of cake. Now we can proceed to the unpacked directory to the bin folder. There are files (executables for both Windows and Linux). What should we use? The idea here is to understand the modes in which server can be run. There are two:
a) standalone mode – which is sufficient for 99% of usages on developer’s machines. It does not mean that it is not suitable for production machines. Server running in standalone just run in one process and whole configuration is specific only to this one machine.
b) domain mode – it is mostly used in production environments as it provides way to keep server’s config consistent using just one machine.
Domain mode does not mean clustering! There is no problem to create cluster using both – standalone or domain mode.
In order to understand basic concepts which are important to Java developers I will use standalone mode in this post. My idea is to present domain and clustering in the future. Sometimes I will mention things related to domain mode (in comparison to standalone).
Having said that we concentrate only on bin/standalone.bat executable (I am working on Windows, Linux users should be familiar with .sh scripts). To separate run-scripts from configuration there is additional config file named standalone.conf.bat, that is used by run-script to customize configuration. Usually when there is no previous JBoss (which in fact means there is no global JBOSS_HOME variable set) we need no additional configuration (besides set JAVA_HOME). Before we start the server we can look around bin folder:
a) adduser.bat – adds user to the server security realm.
b) application-client.bat – it starts lightweight container for client applications that communicate with JBoss. More can be found in this link.
c) init.d – folder containing example run-scripts for running JBoss as a service on linux machine. Be careful! The script may need tweaking to run seamlessly on your system.
d) jboss-cli – I will describe this utility later. It is management utility allowing admins to change server configuration from command line
e) jconsole.bat – widely known tool to monitor working JVM
f) jdr.bat – JBoss Diagnostic Reporter. It will collect useful data from the server, resulting in ZIP file which can be used eg. by support from JBoss
g) run.bat – legacy launch script, not used
h) vault.bat – command line tool to secure sensitive data
i) wsconsume/wsprovide – are command line tools (and also Ant tasks) to generate webservice from WSDL (wsconsume) or from endpoint class (wsprovide)
Now we know our way around. We can finally start Wildfly in standalone mode and the end of run process should be logged similar to this:
21:00:18,761 INFO [org.jboss.ws.common.management] (MSC service thread 1-3) JBWS022052: Starting JBoss Web Services – Stack CXF Server 4.3.2.Final
21:00:19,045 INFO [org.jboss.as] (Controller Boot Thread) JBAS015961: Http management interface listening on http://127.0.0.1:9990/management
21:00:19,048 INFO [org.jboss.as] (Controller Boot Thread) JBAS015951: Admin console listening on http://127.0.0.1:9990
21:00:19,050 INFO [org.jboss.as] (Controller Boot Thread) JBAS015874: WildFly 8.2.0.Final “Tweek” started in 16305ms – Started 184 of 234 services (82 services are lazy, passive or on-demand)
In order to check if everything is ok we can download sample applications for Wildfly from official GitHub page. The most basic is of course helloworld. Just go to the folder You cloned the code and issue the command (with server still running):
mvn clean package wildfly:deploy
In server’s log we should see something like this:
21:21:39,944 INFO [org.wildfly.extension.undertow] (MSC service thread 1-8) JBAS017534: Registered web context: /wildfly-helloworld
21:21:40,894 INFO [org.jboss.as.server] (management-handler-thread – 1) JBAS018559: Deployed “wildfly-helloworld.war” (runtime-name : “wildfly-helloworld.war”)
Right now the only thing left to se is working application. We can visit http://localhost:8080/wildfly-helloworld and see if everything is ok. There should be plain and simple Hello World message on the screen.
Main idea behind Jboss lately is to avoid editing XML files in order to perform administrative tasks. It is good thing – while doing changes using prepared application it is possible to perform additional validation, which avoid errors. By default console application is accessible on port 9990, although if we visit it right now that is the view we are going to see:
As mentioned we must create user to access the app. Remember the list of additional scripts in bin folder? There was script add-user.bat – we are going to use it right now. Process is simple – just add new Management User and follow the questions on the screen. When finished, You can log in http://localhost:9990/console and see something like this.
It means we have admin user and server is working properly. More about admin-related tasks can be found on Akquinet.
So how to deploy an app?
When we do not want to use Maven plugins deployment process is fairly simple.
- GUI application – just visit Deployments tab in this app and point to existing file.
- Auto deploy – the same way as it was done in previous versions. Just copy new file to standalone/deploy folder and it will be picked up by server automatically.
- CLI deployment – quite obvious (example taken from the docs):
// run jboss-cli.bat // type 'connect' to connect to running instance [standalone@localhost:9999 /] deploy ~/Desktop/test-application.war 'test-application.war' deployed successfully. [standalone@localhost:9999 /] undeploy test-application.war Successfully undeployed test-application.war.
Where are my logs?
At the end I will describe problem I’ve faced while deploying my app to development server. The title is right – I could not find my log files. On my local machine slf4j and logback were used, creating two separate files with logs. One for SQL statements and one for everything else. When I deployed application to the Jboss it did not work.
Wildfly has modular architecture. Logging is performed by logging subsystem that can be configured in several ways (yep, console application is one of them). But before that subsystem kicks in, server logging during startup is done via logging.properties file, that resides in configuration directory. I saw that file and was sure that this is final config. Unfortunately it is not. As I’ve mentioned – it is used only before logging subsystem starts.
This subsystem has simple property – add-logging-api-dependencies, that when set to true will force server to provide logging libraries and dependencies. That makes my application’s logging config not working. To fix that I could change above setting, but it was impossible as it affects whole server. So there is another solution. I’ve added file jboss-deployment-structure.xml to my WEB-INF. It is one of deployment descriptors recognized by JBoss. The file looked like this:
<jboss-deployment-structure> <deployment> <exclusions> <module name="org.slf4j" /> <module name="org.slf4j.impl" /> <module name="org.slf4j.api" /> <module name="org.slf4j.jcl.over.slf4j" /> <module name="org.apache.log4j" /> <module name="ch.qos.logback.core" /> <module name="ch.qos.logback.classic" /> </exclusions> </deployment> </jboss-deployment-structure>
It excludes modules with given name, but can be done better as described in this forum thread
<jboss-deployment-structure> <deployment> <!-- exclude-subsystem prevents a subsystems deployment unit processors running on a deployment --> <!-- which gives basically the same effect as removing the subsystem, but it only affects single deployment --> <exclude-subsystems> <subsystem name="logging" /> </exclude-subsystems> </jboss-deployment-structure>
After deployment everything started to work as expected.