Springfox - change path of swagger-ui - spring-boot

now swagger is served from http://localhost:8080/myContextRoot/swagger-ui.html
Can I configure swagger and its resources to be served under http://localhost:8080/myContextRoot/swagger/swagger-ui.html
thank you for your help!

I've followed this approach:
Dependency:
implementation 'org.tuckey:urlrewritefilter:4.0.4'
UrlRewrite Class:
#Component
public class SwaggerUrlRewriteFilter extends UrlRewriteFilter {
private static final String CONFIG_LOCATION = "/urlrewrite.xml";
#Value("classpath:/urlrewrite.xml")
private Resource resource;
#Override
protected void loadUrlRewriter(FilterConfig filterConfig) throws ServletException {
try {
//Create a UrlRewrite Conf object with the injected resource
Conf conf = new Conf(filterConfig.getServletContext(), resource.getInputStream(), resource.getFilename(), "##yourOwnSystemId##");
checkConf(conf);
} catch (IOException ex) {
throw new ServletException("Unable to load URL rewrite configuration file from " + CONFIG_LOCATION, ex);
}
}
}
and in the resource folder urlrewrite.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 4.0//EN"
"http://www.tuckey.org/res/dtds/urlrewrite4.0.dtd">
<urlrewrite>
<rule>
<from>/swagger/swagger-ui.html</from>
<to type="passthrough">/swagger-ui.html</to>
</rule>
<rule>
<from>/swagger/webjars/(.*)</from>
<to type="passthrough">/webjars/$1</to>
</rule>
<rule>
<from>/swagger/v2/api-docs</from>
<to type="passthrough">/v2/api-docs</to>
</rule>
<rule>
<from>/swagger/configuration/(.*)</from>
<to type="passthrough">/configuration/$1</to>
</rule>
<rule>
<from>/swagger/swagger-resources</from>
<to type="passthrough">/swagger-resources</to>
</rule>
</urlrewrite>
after that the path to swagger is:
http://localhost:8080/myContextRoot/swagger/swagger-ui.html

Related

Testing apache camel routes

I have an application build using Apache Camel 2.15.3. And I'm wiring the routes using spring-xml for dependency injection. I'm having a hard time understanding how to write automatic test for my routes. For example I might have the routes:
<onException id="Exception">
<exception>java.lang.Exception</exception>
<handled>
<constant>true</constant>
</handled>
<to uri="direct:fear"/>
</onException>
<route id="happyStory">
<from uri="direct:inTheBeginning"/>
<to uri="bean:enchantedKingdom?method=warn" />
<to uri="bean:fluffykins" />
</route>
<route id="scaryStory">
<from uri="direct:fear"/>
<onException>
<exception>java.lang.Exception</exception>
<handled>
<constant>true</constant>
</handled>
</onException>
<to uri="bean:monster"/>
<choice>
<when>
<simple>${header.succesfullywarned}</simple>
<to uri="bean:enchantedKingdom?method=hide"/>
</when>
<otherwise>
<to uri="bean:enchantedKingdom?method=panic" />
</otherwise>
</choice>
</route>
And I wan't to be able to say that when the bean method warn is called then the header "succesfullywarned" should be set in the message and then when the bean fluffykins is called there should be a exception that causes the message to get sent to "scaryStory" and in this case I wan't to assert that the bean method hide is called.
This is roughly my test class setup:
#RunWith(CamelSpringJUnit4ClassRunner.class)
#ContextConfiguration({"/META-INF/spring/route-
stories.xml","/META-INF/spring/beans.xml"})
#MockEndpointsAndSkip("(bean:fluffykins|bean:monster|bean:enchantedKingdom?method=warn|bean:enchantedKingdom?method=hide|bean:enchantedKingdom?method=panic)")
public class StoryHappyRouteTest extends CamelSpringTestSupport {
private String url = "direct:inTheBeginning";
#Autowired
private ApplicationContext applicationContext;
#Override
protected AbstractApplicationContext createApplicationContext() {
return (AbstractApplicationContext)applicationContext;
}
#Test
public void test(){
MockEndpoint warn = getMockEndpoint("mock:bean:enchantedKingdom?method=warn");
MockEndpoint fluffy = getMockEndpoint("mock:bean:fluffykins");
MockEndpoint monster = getMockEndpoint("mock:bean:monster");
MockEndpoint hide = getMockEndpoint("mock:bean:enchantedKingdom?method=hide");
MockEndpoint panic = getMockEndpoint("mock:bean:enchantedKingdom?method=panic");
fluffy.whenAnyExchangeReceived(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
System.out.println("Bunny!");
throw new NullPointerException();
}
});
template.sendBody(url,"");
warn.assertExchangeReceived(0);
fluffy.assertExchangeReceived(0);
monster.assertExchangeReceived(0);
panic.assertExchangeReceived(0);
}
}
I've read the chapter on testing in the first edition of Camel in action and look around in the manual (http://camel.apache.org/testing.html) but I don't understand how to apply it in my situation. In the above test everything works except where I have bean with multiple methods so I have an uri that contains "?method=methodname", and for some reason this makes it not work. I don't get an error or but the mock is not used and instead the actual beans are called.
Is it not possible to do what I wan't to do? I can change the test setup in any way, but it is a given that the routes and the beans are defined in the spring-xml files.
I've taught about mocking the beans themselves and not the endpoints but the only way I can think of doing that is creating a "imposter-beans.xml" file where all the beans are defined, that points to stubbclasses that extend every class used in the routes. But that feels like an elaborate and wrong approach.
You can write code what to do when the mock receives a message. This is covered in the book in section 6.2.6, where you can use methods like whenAnyExchangeReceived or whenExchangeReceived, and in those inlined processors you can set the header, or throw an exception etc. See for example listing 6.9.

skipAnnotations ignored in Maven PMD plugin

I'm specifying skipAnnotations with value true for the default PMD strings.xml ruleset:
<rule ref="rulesets/java/strings.xml">
<properties>
<property name="skipAnnotations" value="true"/>
</properties>
</rule>
It is ignored in a simple case like
public class NewMain {
#SuppressWarnings("PMD.UnusedFormalParameter")
private void method1(Object arg1) {
System.out.println("method1");
}
#SuppressWarnings("PMD.UnusedFormalParameter")
private void method2(Object arg1) {
System.out.println("method2");
}
#SuppressWarnings("PMD.UnusedFormalParameter")
private void method3(Object arg1) {
System.out.println("method3");
}
#SuppressWarnings("PMD.UnusedFormalParameter")
private void method4(Object arg1) {
System.out.println("method4");
}
}
i.e. mvn validate fails due to Failed to execute goal org.apache.maven.plugins:maven-pmd-plugin:3.8:check (pmd-check) on project pmd-skip-annotations-demo: You have 1 PMD violation. [...].
A MCVE is at https://github.com/krichter722/pmd-skip-annotations-demo.
I'm using maven-pmd-plugin 3.8.
The property corresponds to a given rule, not to the whole ruleset. Therefore, your configuration is invalid, you should write:
<rule ref="rulesets/java/strings.xml/AvoidDuplicateLiterals">
<properties>
<property name="skipAnnotations" value="true"/>
</properties>
</rule>
To include the whole strings ruleset, but have this property, you should write
<rule ref="rulesets/java/strings.xml">
<exclude name="AvoidDuplicateLiterals"/>
</rule>
<rule ref="rulesets/java/strings.xml/AvoidDuplicateLiterals">
<properties>
<property name="skipAnnotations" value="true"/>
</properties>
</rule>

Axis2 with Spring inside AAR cannot find Spring libs

I use Axis2 with Spring and Hibernate. All the Spring libs are located in the AAR/lib folder. But when starting the initializing method this is thrown:
...Caused by: java.lang.ClassNotFoundException: org.springframework.context.ApplicationContextAware
This is my Spring init service:
<service name="SpringInitService"
class="services.implementations.SpringInitService">
<parameter name="ServiceTCCL">composite</parameter>
<parameter name="ServiceObjectSupplier">org.apache.axis2.extensions.spring.receivers.SpringAppContextAwareObjectSupplier
</parameter>
<parameter name="SpringBeanName">SpringInitService</parameter>
<!-- <parameter name="load-on-startup">true</parameter> -->
<operation name="getValue">
<messageReceiver
class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver" />
</operation>
</service>
The startup method:
#SuppressWarnings("resource")
public void startUp(ConfigurationContext ignore, AxisService service) {
ClassLoader classLoader = service.getClassLoader();
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
new String[] { "classpath:spring/applicationContext.xml" }, false);
applicationContext.setClassLoader(classLoader);
applicationContext.refresh();
}
Note: I do not want to move the libs in the WEB-INF/lib
Please, help!

Apache Camel: Weave does not work in Split. Why?

I have the following XML DSL context definition in spring:
<beans>
<camelContext>
<route>
<from uri="direct:foo"/>
<split parallelProcessing="true">
<simple>${body}</simple>
<to uri="direct:bar"/>
</split>
</route>
</camelContext>
</beans>
In my test I'm trying to weave the direct:bar endpoint like so:
context.getRouteDefinitions().get(0).adviceWith(context, new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception {
weaveByToString(".*direct:bar.*").replace().to("mock:bar");
}
});
This successfully works. But when route is starts an exception is thrown saying org.apache.camel.NoSuchBeanException: No bean could be found in the registry for: direct:bar.
Why?
May be camel does not support weaving inside split?
Note: Everything works just fine with following XML:
<beans>
<camelContext>
<route>
<from uri="direct:dummy"/>
<to uri="direct:bar"/>
</route>
<route>
<from uri="direct:foo"/>
<split parallelProcessing="true">
<simple>${body}</simple>
<to uri="direct:dummy"/>
</split>
</route>
</camelContext>
</beans>
I could not reproduce your error with the use case described using Camel 2.7. Here is my test that pass:
#Test
public void test() throws Exception {
context.getRouteDefinitions().get(0).adviceWith(context, new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception {
weaveByToString(".*direct:bar.*").replace().to("mock:bar");
}
});
MockEndpoint mock = getMockEndpoint("mock:bar");
mock.expectedMessageCount(1);
template.sendBody("direct:foo", "this is a test");
assertMockEndpointsSatisfied();
}
Starting the route using camel:run also start without throwing a NoSuchBeanException.

Spring Web Flow and Url Rewrite Filter - cleaning URLs

I'm working on Spring MVC + Web Flow web application. I have mapped /home to MVC Controller and /test to Flow Controller. To remove /app from URLs i'm trying to use Url Rewrite Filter.
Mappings in MVC Controllers (#Controller) works good with that:
http://localhost:8080/spring/home -> render home view.
But when a request goes to WebFlow Controller something is wrong resulting in Error 404:
http://localhost:8080/spring/test -> redirect to http://localhost:8080/spring/app/test?execution=e1s1 -> page not found.
How to remove /app from URLs and got everything working ?
urlrewrite.xml:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN" "urlrewrite3.0.dtd">
<urlrewrite default-match-type="wildcard">
<!-- to remove /app -->
<rule>
<from>/**</from>
<to>/app/$1</to>
</rule>
<outbound-rule>
<from>/app/**</from>
<to>/$1</to>
</outbound-rule>
</urlrewrite>
Dispatcher servlet mapping:
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Simple controller:
#Controller
public class MainController {
#RequestMapping(value={"/home", "/"})
public String index(Model model) {
return "index";
}
}
Some logs:
DEBUG [FlowHandlerMapping:108] : Mapping request with URI '/spring/app/test' to flow with id 'test'
DEBUG [FlowExecutorImpl:135] : Launching new execution of flow 'test' with input null
DEBUG [FlowDefinitionRegistryImpl:59] : Getting FlowDefinition with id 'test'
DEBUG [FlowExecutionImplFactory:78] : Creating new execution of 'test'
...
DEBUG [FlowExecutionImpl:417] : Assigned key e2s1
DEBUG [FlowHandlerAdapter:367] : Sending flow execution redirect to '/spring/app/test?execution=e2s1'
DEBUG [DispatcherServlet:824] : Null ModelAndView returned to DispatcherServlet with name 'spring': assuming HandlerAdapter completed request handling
DEBUG [DispatcherServlet:674] : Successfully completed request
DEBUG [DispatcherServlet:693] : DispatcherServlet with name 'spring' processing GET request for [/spring/app/app/test]
DEBUG [FlowHandlerMapping:114] : No flow mapping found for request with URI '/spring/app/app/test'
WARN [PageNotFound:947] : No mapping found for HTTP request with URI [/spring/app/app/test] in DispatcherServlet with name 'spring'
Temporarily i did it as here using customized FlowHandler. It works, but i think it must be a simpler solution...
package utils;
public class PrettyFlowUrlHandler extends DefaultFlowUrlHandler {
#Override
public String createFlowDefinitionUrl(String flowId, AttributeMap input, HttpServletRequest request) {
return cleanUrl(super.createFlowDefinitionUrl(flowId, input, request), request);
}
#Override
public String createFlowExecutionUrl(String flowId, String flowExecutionKey, HttpServletRequest request) {
return cleanUrl(super.createFlowExecutionUrl(flowId, flowExecutionKey, request), request);
}
protected String cleanUrl(String url, HttpServletRequest request) {
String pattern = request.getServletPath().substring(1) + "/";
return url.replaceFirst(pattern, "");
}
}
config:
<bean id="flowMappings" class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
<property name="flowRegistry" ref="flowRegistry"/>
<property name="flowUrlHandler">
<bean class="utils.PrettyFlowUrlHandler"/>
</property>
<property name="order" value="0" />
</bean>
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
<property name="flowExecutor" ref="flowExecutor"/>
<property name="flowUrlHandler">
<bean class="utils.PrettyFlowUrlHandler"/>
</property>
</bean>
Edit
Not working with custom flow handler like below:
#Component("test")
public class DataHandler extends AbstractFlowHandler {
#Override
public String handleExecutionOutcome(FlowExecutionOutcome outcome,
HttpServletRequest request, HttpServletResponse response) {
// ... checking outcome ...
return "/home"; // redirect to '404 page not found', because of rewrite to `/app/app/home`
}
}
Are you you trying to remove app from your url for eg
http://www.mydomain.com/app/home.html and change it to
http://www.mydomain.com/home.html
If yes then you should be configuring server.xml and your application should be deployed as ROOT instead of app in public_html/ or your tomcat directory.
This will work for you

Resources