diff --git a/examples/rollbar-struts2-spring/build.gradle b/examples/rollbar-struts2-spring/build.gradle new file mode 100755 index 00000000..b36b349d --- /dev/null +++ b/examples/rollbar-struts2-spring/build.gradle @@ -0,0 +1,29 @@ +buildscript { + repositories { + jcenter() + } + + dependencies { + classpath 'com.bmuschko:gradle-tomcat-plugin:2.3' + } +} + +apply plugin: 'war' +apply plugin: 'com.bmuschko.tomcat' + +dependencies { + implementation project(":rollbar-struts2") + + implementation 'javax.servlet:javax.servlet-api:3.1.0' + implementation 'org.apache.struts:struts2-core:2.5.25' + implementation 'org.apache.struts:struts2-spring-plugin:2.5.25' + + def tomcatVersion = '7.0.57' + + tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}", + "org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}" + tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") +} + +tomcatRun.contextPath = '/' +tomcatRunWar.contextPath = '/' diff --git a/examples/rollbar-struts2-spring/src/main/java/com/example/rollbar/struts2/action/HelloRollbarAction.java b/examples/rollbar-struts2-spring/src/main/java/com/example/rollbar/struts2/action/HelloRollbarAction.java new file mode 100755 index 00000000..2d438522 --- /dev/null +++ b/examples/rollbar-struts2-spring/src/main/java/com/example/rollbar/struts2/action/HelloRollbarAction.java @@ -0,0 +1,38 @@ +package com.example.rollbar.struts2.action; + +import com.opensymphony.xwork2.ActionSupport; +import com.opensymphony.xwork2.inject.Inject; +import com.rollbar.notifier.Rollbar; +import com.rollbar.struts.RollbarFactory; +import java.util.concurrent.atomic.AtomicInteger; + + +/** + * Struts2 action with Spring CDI. + */ +public class HelloRollbarAction extends ActionSupport { + + private static final AtomicInteger counter = new AtomicInteger(1); + + private final Rollbar rollbar; + + @Inject + public HelloRollbarAction(RollbarFactory rollbarFactory) { + this.rollbar = rollbarFactory.build(); + } + + public String index() { + rollbar.info("Executing index action in HelloRollbarAction"); + + return SUCCESS; + } + + public String hello() { + int current = counter.getAndAdd(1); + if (current % 2 == 0) { + throw new RuntimeException("Fatal error at hello rollbar action. Number: " + current); + } + return SUCCESS; + } + +} diff --git a/examples/rollbar-struts2-spring/src/main/resources/applicationContext.xml b/examples/rollbar-struts2-spring/src/main/resources/applicationContext.xml new file mode 100644 index 00000000..490e3a5d --- /dev/null +++ b/examples/rollbar-struts2-spring/src/main/resources/applicationContext.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/examples/rollbar-struts2-spring/src/main/resources/struts.xml b/examples/rollbar-struts2-spring/src/main/resources/struts.xml new file mode 100644 index 00000000..cc2ca45f --- /dev/null +++ b/examples/rollbar-struts2-spring/src/main/resources/struts.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + hello + + + + /WEB-INF/jsp/index.jsp + + + + diff --git a/examples/rollbar-struts2-spring/src/main/webapp/WEB-INF/jsp/index.jsp b/examples/rollbar-struts2-spring/src/main/webapp/WEB-INF/jsp/index.jsp new file mode 100644 index 00000000..0812c2da --- /dev/null +++ b/examples/rollbar-struts2-spring/src/main/webapp/WEB-INF/jsp/index.jsp @@ -0,0 +1,16 @@ + + +<%@taglib prefix="s" uri="/struts-tags" %> + + + + Hello Rollbar struts2 example application + + + + Hello Rollbar! + + + \ No newline at end of file diff --git a/examples/rollbar-struts2-spring/src/main/webapp/WEB-INF/web.xml b/examples/rollbar-struts2-spring/src/main/webapp/WEB-INF/web.xml new file mode 100755 index 00000000..f53f5709 --- /dev/null +++ b/examples/rollbar-struts2-spring/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,29 @@ + + + + + contextConfigLocation + classpath*:applicationContext*.xml + + + + struts2 + org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter + + + struts2 + /* + + + + + com.rollbar.web.listener.RollbarRequestListener + + + + org.springframework.web.context.ContextLoaderListener + + \ No newline at end of file diff --git a/examples/rollbar-struts2/build.gradle b/examples/rollbar-struts2/build.gradle new file mode 100755 index 00000000..0590ea86 --- /dev/null +++ b/examples/rollbar-struts2/build.gradle @@ -0,0 +1,28 @@ +buildscript { + repositories { + jcenter() + } + + dependencies { + classpath 'com.bmuschko:gradle-tomcat-plugin:2.3' + } +} + +apply plugin: 'war' +apply plugin: 'com.bmuschko.tomcat' + +dependencies { + implementation project(":rollbar-struts2") + + implementation 'org.apache.struts:struts2-core:2.5.25' + implementation 'javax.servlet:javax.servlet-api:3.1.0' + + def tomcatVersion = '7.0.57' + + tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}", + "org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}" + tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") +} + +tomcatRun.contextPath = '/' +tomcatRunWar.contextPath = '/' diff --git a/examples/rollbar-struts2/src/main/java/com/example/rollbar/struts2/action/HelloRollbarAction.java b/examples/rollbar-struts2/src/main/java/com/example/rollbar/struts2/action/HelloRollbarAction.java new file mode 100755 index 00000000..56cce5d3 --- /dev/null +++ b/examples/rollbar-struts2/src/main/java/com/example/rollbar/struts2/action/HelloRollbarAction.java @@ -0,0 +1,23 @@ +package com.example.rollbar.struts2.action; + +import com.opensymphony.xwork2.ActionSupport; +import java.util.concurrent.atomic.AtomicInteger; + + +/** + * Struts2 action that rises an error every even request number. + */ +public class HelloRollbarAction extends ActionSupport { + + private static final AtomicInteger counter = new AtomicInteger(1); + + public String execute() { + int current = counter.getAndAdd(1); + if (current % 2 == 0) { + throw new RuntimeException("Fatal error at hello rollbar action. Number: " + current); + } + return SUCCESS; + } + + +} diff --git a/examples/rollbar-struts2/src/main/resources/struts.xml b/examples/rollbar-struts2/src/main/resources/struts.xml new file mode 100644 index 00000000..c4fea7ff --- /dev/null +++ b/examples/rollbar-struts2/src/main/resources/struts.xml @@ -0,0 +1,34 @@ + + + + + + + + + + [ACCESS_TOKEN] + true + production + 1.1.2 + + + + + + + + + + + + + + /WEB-INF/jsp/index.jsp + + + + diff --git a/examples/rollbar-struts2/src/main/webapp/WEB-INF/jsp/index.jsp b/examples/rollbar-struts2/src/main/webapp/WEB-INF/jsp/index.jsp new file mode 100644 index 00000000..0812c2da --- /dev/null +++ b/examples/rollbar-struts2/src/main/webapp/WEB-INF/jsp/index.jsp @@ -0,0 +1,16 @@ + + +<%@taglib prefix="s" uri="/struts-tags" %> + + + + Hello Rollbar struts2 example application + + + + Hello Rollbar! + + + \ No newline at end of file diff --git a/examples/rollbar-struts2/src/main/webapp/WEB-INF/web.xml b/examples/rollbar-struts2/src/main/webapp/WEB-INF/web.xml new file mode 100755 index 00000000..2e6f0950 --- /dev/null +++ b/examples/rollbar-struts2/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,20 @@ + + + + + + com.rollbar.web.listener.RollbarRequestListener + + + + struts2 + org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter + + + struts2 + /* + + \ No newline at end of file diff --git a/rollbar-struts2/build.gradle b/rollbar-struts2/build.gradle new file mode 100644 index 00000000..a384708c --- /dev/null +++ b/rollbar-struts2/build.gradle @@ -0,0 +1,8 @@ +ext { + struts2Version = '2.5.25' +} + +dependencies { + api project(":rollbar-web") + implementation 'org.apache.struts:struts2-core:' + struts2Version +} \ No newline at end of file diff --git a/rollbar-struts2/src/main/java/com/rollbar/struts/RollbarFactory.java b/rollbar-struts2/src/main/java/com/rollbar/struts/RollbarFactory.java new file mode 100644 index 00000000..050ede84 --- /dev/null +++ b/rollbar-struts2/src/main/java/com/rollbar/struts/RollbarFactory.java @@ -0,0 +1,103 @@ +package com.rollbar.struts; + +import static com.rollbar.notifier.config.ConfigBuilder.withAccessToken; + +import com.rollbar.notifier.Rollbar; +import com.rollbar.notifier.config.Config; +import com.rollbar.notifier.config.ConfigBuilder; +import com.rollbar.notifier.config.ConfigProvider; +import com.rollbar.notifier.config.ConfigProviderHelper; +import com.rollbar.web.provider.PersonProvider; +import com.rollbar.web.provider.RequestProvider; + +public class RollbarFactory { + + private String accessToken; + + private String userIpHeader; + + private String captureIp; + + private String environment; + + private String codeVersion; + + private String configProviderClassName; + + public RollbarFactory() { + this(null, null, null, null, null, null); + } + + /** + * Constructor. + * @param accessToken the rollbar access token. + * @param userIpHeader request http header name used for getting user ip. + * @param captureIp "true" or "false" values to capture and send user ip. + * @param environment the environment. + * @param codeVersion the code version. + * @param configProviderClassName the class name used to use a custom configuration. + */ + public RollbarFactory(String accessToken, String userIpHeader, String captureIp, + String environment, String codeVersion, String configProviderClassName) { + this.accessToken = accessToken; + this.userIpHeader = userIpHeader; + this.captureIp = captureIp; + this.environment = environment; + this.codeVersion = codeVersion; + this.configProviderClassName = configProviderClassName; + } + + /** + * Build method to create a Rollbar object instance. + * @return the rollbar instance. + */ + public Rollbar build() { + ConfigProvider configProvider = ConfigProviderHelper.getConfigProvider(configProviderClassName); + Config config; + + RequestProvider requestProvider = new RequestProvider.Builder() + .userIpHeaderName(userIpHeader) + .captureIp(captureIp) + .build(); + + ConfigBuilder configBuilder = withAccessToken(accessToken) + .request(requestProvider) + .person(new PersonProvider()) + .environment(environment) + .codeVersion(codeVersion); + + if (configProvider != null) { + config = configProvider.provide(configBuilder); + } else { + config = configBuilder.build(); + } + + return new Rollbar(config); + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + + public void setUserIpHeader(String userIpHeader) { + this.userIpHeader = userIpHeader; + } + + public void setConfigProviderClassName(String configProviderClassName) { + this.configProviderClassName = configProviderClassName; + } + + public void setCaptureIp(String captureIp) { + this.captureIp = captureIp; + } + + public void setEnvironment(String environment) { + this.environment = environment; + } + + public void setCodeVersion(String codeVersion) { + this.codeVersion = codeVersion; + } + +} diff --git a/rollbar-struts2/src/main/java/com/rollbar/struts/interceptor/RollbarExceptionInterceptor.java b/rollbar-struts2/src/main/java/com/rollbar/struts/interceptor/RollbarExceptionInterceptor.java new file mode 100644 index 00000000..cfbf7169 --- /dev/null +++ b/rollbar-struts2/src/main/java/com/rollbar/struts/interceptor/RollbarExceptionInterceptor.java @@ -0,0 +1,99 @@ +package com.rollbar.struts.interceptor; + +import com.opensymphony.xwork2.ActionInvocation; +import com.opensymphony.xwork2.inject.Inject; +import com.opensymphony.xwork2.interceptor.AbstractInterceptor; +import com.rollbar.notifier.Rollbar; +import com.rollbar.struts.RollbarFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RollbarExceptionInterceptor extends AbstractInterceptor { + + private static Logger LOGGER = LoggerFactory.getLogger(RollbarExceptionInterceptor.class); + + private String accessToken; + + private String userIpHeader; + + private String captureIp; + + private String environment; + + private String codeVersion; + + private String configProviderClassName; + + private Rollbar rollbar; + + public RollbarExceptionInterceptor() { + this(null); + } + + /** + * Constructor used with CI. + * @param rollbarFactory the rollbar factory. + */ + @Inject + public RollbarExceptionInterceptor(RollbarFactory rollbarFactory) { + if (rollbarFactory != null) { + this.rollbar = rollbarFactory.build(); + } else { + this.rollbar = null; + } + } + + @Override + public void init() { + if (rollbar != null) { + LOGGER.info("Rollbar instance found by Dependency Injection!. " + + "Ignoring interceptor properties."); + return; + } + + LOGGER.debug("Rollbar instance not found by Dependency Injection!. " + + "Using interceptor properties."); + + RollbarFactory rollbarFactory = new RollbarFactory(accessToken, userIpHeader, captureIp, + environment, codeVersion, configProviderClassName); + this.rollbar = rollbarFactory.build(); + } + + @Override + public String intercept(ActionInvocation actionInvocation) throws Exception { + try { + return actionInvocation.invoke(); + } catch (Exception e) { + rollbar.error(e); + throw e; + } + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + public void setUserIpHeader(String userIpHeader) { + this.userIpHeader = userIpHeader; + } + + public void setConfigProviderClassName(String configProviderClassName) { + this.configProviderClassName = configProviderClassName; + } + + public void setCaptureIp(String captureIp) { + this.captureIp = captureIp; + } + + public void setEnvironment(String environment) { + this.environment = environment; + } + + public void setCodeVersion(String codeVersion) { + this.codeVersion = codeVersion; + } + + Rollbar getRollbar() { + return this.rollbar; + } +} diff --git a/rollbar-struts2/src/test/java/com/rollbar/struts/RollbarFactoryTest.java b/rollbar-struts2/src/test/java/com/rollbar/struts/RollbarFactoryTest.java new file mode 100644 index 00000000..a0dd4af7 --- /dev/null +++ b/rollbar-struts2/src/test/java/com/rollbar/struts/RollbarFactoryTest.java @@ -0,0 +1,16 @@ +package com.rollbar.struts; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; + +public class RollbarFactoryTest { + + @Test + public void testBuild() { + RollbarFactory sut = new RollbarFactory(); + + assertNotNull(sut.build()); + } + +} diff --git a/rollbar-struts2/src/test/java/com/rollbar/struts/interceptor/RollbarExceptionInterceptorTest.java b/rollbar-struts2/src/test/java/com/rollbar/struts/interceptor/RollbarExceptionInterceptorTest.java new file mode 100644 index 00000000..595dc9be --- /dev/null +++ b/rollbar-struts2/src/test/java/com/rollbar/struts/interceptor/RollbarExceptionInterceptorTest.java @@ -0,0 +1,79 @@ +package com.rollbar.struts.interceptor; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.opensymphony.xwork2.ActionInvocation; +import com.rollbar.notifier.Rollbar; +import com.rollbar.struts.RollbarFactory; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +public class RollbarExceptionInterceptorTest { + + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + private RollbarExceptionInterceptor sut; + + @Mock + private RollbarFactory rollbarFactory; + + @Mock + private Rollbar rollbar; + + @Mock + private ActionInvocation action; + + @Before + public void setUp() { + when(rollbarFactory.build()).thenReturn(rollbar); + + sut = new RollbarExceptionInterceptor(rollbarFactory); + } + + @Test + public void testInitWithDI() throws Exception { + sut.init(); + + assertEquals(rollbar, sut.getRollbar()); + } + + @Test + public void testInitWithoutDI() throws Exception { + String accessToken = "test_access_token"; + + sut = new RollbarExceptionInterceptor(); + sut.setAccessToken(accessToken); + + sut.init(); + + assertNotNull(sut.getRollbar()); + } + + @Test + public void testIntercept() throws Exception { + Exception exception = mock(Exception.class); + + when(action.invoke()).thenThrow(exception); + + sut.init(); + + try { + sut.intercept(action); + } catch (Exception e) { + if(!e.equals(exception)) { + fail(); + } + } + verify(rollbar).error(exception); + } +} diff --git a/settings.gradle b/settings.gradle index e88435bd..56e609a9 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,6 +8,7 @@ include ":rollbar-api", ":rollbar-logback", ":rollbar-spring-webmvc", ":rollbar-spring-boot-webmvc", + ":rollbar-struts2", ":examples:rollbar-java", ":examples:rollbar-web", ":examples:rollbar-android", @@ -15,4 +16,7 @@ include ":rollbar-api", ":examples:rollbar-log4j2", ":examples:rollbar-logback", ":examples:rollbar-spring-webmvc", - ":examples:rollbar-spring-boot-webmvc" + ":examples:rollbar-spring-boot-webmvc", + ":examples:rollbar-struts2", + ":examples:rollbar-struts2-spring" +