When deploying an application to JBoss server, for a JAR like ojdbc14.jar (Oracle JDBC), is it better to include this jar in the ear file of the deployment, or should it be deployed to JBoss's server/default/lib folder?
The argument I've been given is that the application needs to support global transactions, hence the datasource must be defined at the application server level (e.g. copied to server/default/lib folder) so it can talk to other app servers, and for that to happen you need the drivers at the app server level.
I'd like to hear what is the correct approach here. Thanks.
I believe this is the correct approach.
You will typically define your datasource outside of your application (outside of your EAR/WAR) using the appropriate configuration files depending upon the application server you are using. Whereas on JBoss, you usually add your configuration to XML files, with WebLogic, you can create a datasource directly using the Admin console.
Given that this datasource will be created on server startup, the necessary libraries (in your case, ojdbc14.jar) must be available on the classpath of the application server.
I have also come across licensing issues where the use of a 3rd party library prevents you from bundling it within your application.
Also, defining your datasource outside of your application means you do not have to perform a rebuild when the datasource configuration needs to change.
So many time I have done that...
I will always put the jar inside the server/default/lib folder if it has something to have about JDBC.
Because your database driver is loaded one time as soon as the server is started, and not each time you deploy/undeploy the webapplication your are working on.
Your datasources will be availiable for any others sub-projects too, and it will be a great advantage when you have a specific project for integration testing purpose.
Related
I'm complete able to configure spring boot in both cases, the question here is which of them are more robust and is the more recommended, because I didn't find in the spring boot documentation the recommended way to deploy it in a production environment, my concerns about use the embedded container are:
If I want to set it as a Windows or Linux service, is the jar file the best option?
If I use the jar file I'm not going to have access to restart the server.
Maybe in the future I need more applications in the same container.
If I restart the machine I have to execute again the java -jar.
The question in general is which is better use the jar file and execute it as java -jar jarname.jar in production or change the packaging to war set the tomcat as provided and set the generated war in an empty tomcat.
I hope you can help me.
---EDIT---
Many times the answer is depends, this is for a normal web application or REST web service.
jar packaging is perfectly suitable for production and you should rather fallback to war only if you really have to - which is often the case when you cannot control your deployment environment (which is often the case in large enterprises).
There is a chapter in Spring Boot Reference about setting up Spring Boot based application as a Unix/Linux/Windows service: Installing Spring Boot applications.
Regarding your concern:
Maybe in the future I need more applications in the same container.
With embedded containers if you need more applications running on the same machine, you should start two applications separately, each running on different port and effectively you will end up with two containers running - which is good, applications are better isolated from each other.
About a month ago I had the question like yours.
Let me share my conclusion:
1) JAR:
You can run independently every appliction with different ports (in linux, java -jar ... > app_logs.log &) and you can route it (e.g. nginx). Note that, restarting is not problem. You can write custom bash script (like this: ps aux | grep appname and kill by PID)
But there are some problems with configuring production app. Property files will archived into jar.
2) WAR
You can deploy into container and just run it. Easy managing at the server. If you want to re-configure app, open properties file from unarchived folder inside container, change it as need and restart container. So, managing and configuring will be easy.
But, if you want to run another app in this server with another port, then you must install another copy of container and config it.
So, in my practice, using war app easier than jar to manage and re-configure.
I don't know that much about Windows services but on Linux you can add the execution of a jar to a RC-Scripts (and thus make the application start at a certain run-level). For a spring boot app you just have to symlink to the jar and you can start/stop/etc like any other service, see: Spring Boot application as a Service
restart the machine or the JVM? A shutdown mechanism is built into spring boot, you just have to activate it (and you should enable security machanism so that not anybody can do that), see: How to shutdown a Spring Boot Application in a correct way?
Spring-Boot enables microservices - so the idea is to have one embedded webapp-container for each webapp/microservice. This reduces the risk of losing all services when only one is going down.
Yes. and you have to execute catalina.sh|bat start after every restart. Or you add an appropriate startup script (see 1.)
I sense that you'd rather do it the old-fashioned way. Despite the 'matter of taste' answer, there is one argument pro-jar: the only dependency is the JVM! The rest (the web-app-container, db-drivers, other libraries) is all part of the package you deliver. And if you decide to change the container for the next release, so will it be.
One more reason to use "war" file in production.
Springboot masked an error Jetty threw whereas WAR deployed in Jetty correctly caught it ( though issue below is still under review )
https://github.com/spring-projects/spring-boot/issues/8917#issuecomment-294673487
I don't know much about server kind of things, But my recommendation is
If you are using Monolithic application, better to use war with
external tomcat.
If you are using for Micro Service applications, use embedded
tomcat with different port. And each micro service applications are
independent from each other.
I have a multi-tier project where the application server that provides an access point to the web should deploy its WAR file only if required remote JNDI resources are available.
The JNDI lookup is performed on a different server within the local network, where no access from the outside world is allowed.
My problem is that right now, there is no way to tell if any of the required EJB modules are in place before starting deployment of the WAR - which will fail miserably if a JNDI lookup is not resolved (the remote services are used with Dependency Injection, so they must be present at startup).
Of course, I could set up a timer in my Maven build to wait for an arbitrary number of seconds between deployment of the modules, to allow the EJBs to start, but that seems like a crude hack to me, and it will not be very reliable, depending on which machine does the build.
I would be happy both if an JNDI check can be done directly on the application server, or within the Maven build, prior to deployment.
Is there something like that? I found this question, but there never was an answer...
I haven't tried it, but this should be possible with #Resource, or by creating WEB_INF/ejb-jar.xml and using lookup-name. See https://community.jboss.org/thread/213106.
My application, when running on Tomcat, is not able to connect to my database when deployed as a .war in the webapps folder, but it can connect when I am running it through Eclipse directly. The code is exactly the same in both cases. In addition, other apps in the webapps folder, which originally could connect to the database, can no longer do so. The jdbc code is correct as I have tested it with offline applications or when running it through eclipse, but not when I access it on, say, Chrome, using localhost. What has happened to my tomcat server?
Note: the JDBC driver is the MS Access one.
The code is exactly the same in both cases.
No it's not; if it were exactly the same you'd be connecting properly.
but it can connect when I am running it through Eclipse directly
Does this mean that you have a main method that drives the code that connects properly? The way you do it is usually different from a web app - you know that, right?
If you could post an exception or log message it would help a great deal.
I'm guessing it could be any one of the following; guessing is necessary because you haven't provided enough information for a solid answer:
The JDBC driver JAR is not available when you run under one configuration; you'll see a ClassNotFoundException in that case.
You haven't configured a JNDI data source properly in Tomcat.
You didn't put the JDBC driver JAR in the Tomcat /lib directory.
Could be other possibilities.
UPDATE:
Since you're using Access, and providing no other information, I'm guessing that you're using a relative file path to get to the Access .mdb file. Your command line app that runs successfully in Eclipse works because you give a relative file path that is correct relative to the project root. When you deploy to Tomcat, that relative path is no longer correct, so your application can't find the database anymore.
Sounds like you aren't printing the stack trace for errors, so you're losing out on information that might help you figure this out.
Microsoft Access is not a multi-user database. A web based application running on Tomcat is certainly multi-threaded. You should not be using Access for a web application. I'd consider switching to another database.
First, you need to verify the path to your database file. In fact, I believe it has to be an absolute path for tomcat to work correctly. The simplest thing to do is to put your database file in C:\data or similar and then hard code the path in your code. Of course, the file will be outside of your war and thus not portable (i.e., deployable to a remote server).
Second, you do need to make sure that the JDBC driver is available. If you use Class.forName in your code to load the driver, you will only need to make sure that the jar containing the driver is in the tomcat classpath (which would include the lib directory of your webapp). If you use the -Djdbc.drivers JVM flag approach, you will need to add it to the tomcat startup scripts.
As part of all the development of some use cases, I've used a properties file approach to handle almost all the configuration parameters in the project.
Even when this approach is a security safe approach, I need to be able to change this parameters on the application, so I need an admin web module to be able to change at runtime all the configuration on the properties file.
I would like to know if there's any WAR that I can put on my website to enable dynamic web application modification.
I found that the Apache Commons Configuration enables me to do runtime modifications, but I haven't found a CRUD application for properties files.
Does anyone know one?
Agreed with Isaac's and ruffp's comments. Even if you did manage a way to update the contents of the property files at runtime, this wouldn't solve the issue that most of the properties are likely loaded once and not read again until the application is restarted. You're best off using Java EE environment entries, or a backing database.
Another option is to use JMX management beans. These beans could then be accessed through any JMX management tool, including jconsole - or your could use any available web front-end to access them as well, including any provided by an application server.
For a typical J2EE web application, the datasource connection settings are stored as part of the application server configuration.
Is there a way to version control these configuration details? I want more control on the datasource and other application server config changes.
What is the standard practice for doing this?
Tracking configuration changes to your application server through version control is a good thing to ask for. However, It does imply that all changes are done via scripting, instead of the administrative web interface. I recommend
http://www.ibm.com/developerworks/java/library/j-ap01139/index.html?ca=drs-
as a good background information article on this topic.
Update: Just recently, part 2 has been published here: http://www.ibm.com/developerworks/java/library/j-ap02109/index.html?ca=drs-
When working with WebSphere we found the best approach was to script the deployment and place the script under version control plus the response files for each of the target environments.
Websphere canbe tricky as the directory structure is a mess of files - often there appears to be duplicates and it's hard to figure which is the magic file you need to backup / restore . The question of how to go about this should not detract from the need to do it. - which is a definite yes.
Our (Spring) apps have a hardcoded jndi name in the spring config file. That way, the same ear can be deployed to dev, qa and prod environments, and you don't have to worry about database connection details.
The app server admins ensure that a datasource is registered against that jndi name, with the connection details as appropriate on each environment.
But how does this let me manage changes to datasource configurations in the application servers. Here's a scenario:
DBAs change the connection password of the database server.
Webspehere/Weblogic administrator makes corresponding changes to server configuration through administrator console.
The above change is not version controlled so there is no clean way of knowing the history of such changes.
The problem is not about how the application should be configured but about how the configuration changes should be version controlled. Perhaps it sounds like an overkill for simple projects but for some projects, controlling changes like these really becomes a problem.
Any time you ask yourself "should X be in version control" the default answer is "yes".
For a more refined answer, ask yourself this: is the file created by a person (like a source file or a document) or is it generated by another program (like an object file or a distribution PDF)?
File that are created, and/or maintained, by a human should be under configuration control.
We are always using version control for our app server settings. It's a tool called WLST (weblogic scripting tool) which is part of the weblogic server distribution. The domain configuration is stored within a Jython script, which can easily be executed via command line and therefore integrates superb with our build tool maven.
Creating a preconfigured running weblogic domain only needs to execute a maven goal. All those annoying problems of misconfigured jdbc connections or wrong jms destination parameters are gone. You will always have a appserver configuration which matches the source code at a given time. You will never need to remember which app server setting must be applied for this specific version of the project you are working on.
I really recommend this.
I also would like to know, if there are similar solutions for other application server available. As far as i know there is a way for glassfish via ant. How this can be achieved for JBoss?