I work from home for a company where we write enterprise Java web applications using Spring, Hibernate for Tomcat and use Maven. A couple of months ago, when I started working from home, my manager agreed to buy me a copy of IntelliJ IDEA so I could be more productive than when I was when I was using Eclipse (which is an IDE I love and still use for other projects, but is also a memory hog).

While I have been using IntelliJ for sometime now, I haven’t had a lot of success in configuring Tomcat to run through the IDE. I followed the steps on the official help page, but it didn’t seem to work with my Maven project. So I added a configuration descriptor to Tomcat to load the target directory of my Maven project each time it loads and when I want to run my code, I produce an exploded war through IntelliJ and then run Tomcat externally.

When I had to debug my code, I would print out debugging statements which would help me narrow down the places in my code where the bug was, and then I would just inspect it manually. Not really the best way to debug code, but I really didn’t have the time to integrate Tomcat into IntelliJ.

Last night, I had a NullPointerException in a Java Spring project I’ve been working on for a couple of months now, and this approach didn’t work, and I set out to integrate Tomcat with IntelliJ once and for all.

When I had first tried to integrate Tomcat with IntelliJ, I had followed the steps on the Jetbrains Wiki and that worked just how it was described, but when I tried to run or debug my Maven project through IntelliJ, it just would not work.

After a lot of Googling and Binging *wink*, I had found no single source that explained how this should be done, and I spent a major part of last night just playing with different combinations of the different settings and was finally able to set it up correctly (I hope). Now, I am able to run and debug Maven projects directly through Tomcat and trust me, life is better.

I’m not sure if there’s other people who’ve been through the same experience as I have, so I’ve decided to put together this guide. Hope someone who is in the same position as I was yesterday will get something out of it.

1. Add your Tomcat configuration to IntelliJ through Settings -> Application Servers -> Add. Both Tomcat Home and Tomcat Base Directory should be set to your tomcat installation directory (e.g. C:\Tomcat6.0.33)

Adding Tomcat 6 to IntelliJ Settings

Adding Tomcat 6 to IntelliJ Settings

2. Add a Run/Debug Configuration to your IntelliJ project.

Edit Run/Debug Configuration

Edit Run/Debug Configuration

3. Click the + and add a new Tomcat local default configuration. Give it a name and you can have it start your browser automatically and go to a startup page.

New Tomcat Configuration

New Tomcat Configuration

4. On the Before Launch frame, check Make.

Before Launch Make

Check Make

5. Click the ellipses (….) button next to Build Artifact and check exploded war.

Exploded war Build

Exploded war Build

6. Similarly for Maven, click the ellipses (…) button next to Run Maven Goal and select package.

Maven Package

Maven Package

7. On the Deployment tab, in the Deploy at Server Startup section, add a new Exploded war Artifact.

Deploy at Server Startup

Deploy at Server Startup

(Steps below show how to configure the IntelliJ debugger to connect to Tomcat)

8. On the Startup/Connection tab, Select Debug from the left pane and set the port to 8000.

Debug Port

Set Debug Port

9. Create two new environment variables (Directions here for *nix and Windows)

JPDA_ADDRESS=8000
JPDA_TRANSPORT=dt_socket

And you’re set. Now when you click Run or Build, you should see maven packaging the project and work it’s ‘magic’, and then Tomcat should run with the new app!

Maven doing its magic

Maven doing its magic

While now it seems simple, this was not at all intuitive when I was first tried to set all this up. But now that I have got this set up, my workflow is a lot improved and I can go back to focusing on the code!

Alternatively, if you wanted to run your project outside of IntelliJ, you can put a configuration descriptor into your tomcat/conf/Catalina/localhost directory to automatically look in a directory and deploy it every time it starts. For my QEF project, I have a file qef.xml that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<Context docBase="/programming/appQef/target/qef">
    <Manager className="org.apache.catalina.session.PersistentManager" maxInactiveInterval="600" saveOnRestart="false"/>
    <ResourceLink name="jdbc/qef" global="jdbc/qef" type="javax.sql.DataSource" />
    <ResourceLink global="config/machine" name="config/machine" type="java.lang.String"/>
    <ResourceLink global="config/envType" name="config/envType" type="java.lang.String"/>
    <ResourceLink global="config/envLocation" name="config/envLocation" type="java.lang.String"/>
</Context>

Now whenever I want to execute my program, I build an exploded war through IntelliJ and start Tomcat, which looks for the exploded war in the given directory and automatically deploys it.

Thanks to this and this, I was able to figure it all out. Thanks Matt and Piotr!

Hope this will help somebody out as well. :)

Tagged with:
 

9 Responses to How to set up Maven/Tomcat to build & run & debug through IntelliJ

  1. Great! thanks for the share!
    Arron

    • David says:

      Честно говоря, особо эту тему не раскапывал. При беглом поиске хороших бесплатных альтернатив не нашлось. Разве что , но он очень сильно уступает JRebel по функционалу и удобству использования. Пока искал : Now all very well, isn’t there a free alternative? Well yes, the basic ftucnion it does is fairly simple, and there’s something called Hotswap which is free. However the money is in the details, Java is more complicated nowadays than just loading a class, modern design pattern has more dependencies such inheritance, interfaces, annotations etc. All the basic ftucnion or Hotswap can do is allow us to modify the inners of an existing method which is not quite enough. JRebel not only support these design pattern, they’ve even went all the way to support technologies ‘as a whole’ such as JSF, Hibernate, EJBs, Guice etc… Now this requires a lot of development as most Java developer knows, using any of these library can be a beast, let alone working along side it. So I can see why the high licence premium

    • Piscis says:

      That’s a clever answer to a tricky quesiotn

  2. Kendrick says:

    Really good information! I have been seeking something like this for quite a while now. Many thanks!

    • Jhon says:

      А ну вот оказывается надо было просто запустить:/usr/share/javadb/bin/startNetworkServerТеперь кое что другое не понятно. Когда захожу в выдает ошибку:An Error Occurred:null source- Stack Tracejava.lang.IllegalArgumentException: null socraeut java.util.EventObject.(EventObject.java:38)at javax.faces.event.SystemEvent.(SystemEvent.java:67)at javax.faces.event.ComponentSystemEvent.(ComponentSystemEvent.java:69)at javax.faces.event.PostRestoreStateEvent.(PostRestoreStateEvent.java:69)at com.sun.faces.lifecycle.RestoreViewPhase.deliverPostRestoreStateEvent(RestoreViewPhase.java:256)at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:245)at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:97)at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:107)at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:114)at javax.faces.webapp.FacesServlet.service(FacesServlet.java:308)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:368)at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:112)at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:177)at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)at org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:109)at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:169)at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)at java.lang.Thread.run(Thread.java:662)Это что то не реализовано у тебя или мне надо что то еще настроить?

  3. D:/usr/mmine/eclipse/tomcat/6.0/conf/Catalina/localhost

  4. Rudy says:

    What liberating knowledge. Give me lierbty or give me death.

  5. selim says:

    haha AND me. $AuthenticationProviderCacheResolver#0 : Instantiation of bean failed; nteesd exception is java.security.AccessControlException: access denied (java.lang.reflect.ReflectPermission suppressAccessChecks)Permission,Permission again I know,i gotta update the version too.

  6. Leo says:

    Ah yes, nicely put, evreynoe.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>