Camel: using property placeholders for boolean attribute in CXF endpoint configuration - apache-camel

I like to use a property placeholder for a Boolean attribute in my CXF endpoint definition.I've read the doc about the placeholder prefix in http://camel.apache.org/using-propertyplaceholder.html but ik cannot figure out how to apply them in my endpoint configuration. String placeholders work fine. In the example below I use Boolean attribute ${ws-logging}, and the XML won't validate. How can I use a property placeholder for a Boolean attribute in a CXF endpoint configuration?
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:prop="http://camel.apache.org/schema/placeholder"
xmlns:camel-cxf="http://camel.apache.org/schema/blueprint/cxf"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
<property-placeholder persistent-id="test.config" id="test.config.placeholder" xmlns="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0">
<default-properties>
<property name="ws-logging" value="true"/>
</default-properties>
</property-placeholder>
<camel-cxf:cxfEndpoint id="update"
address="http://someaddress"
endpointName="ssp:someendpoint"
serviceName="ssp:someservice"
wsdlURL="http://someaddress/wsdl?targetURI=sometargeturi"
xmlns:ssp="somenamespace"
loggingFeatureEnabled="${ws-logging}">
<camel-cxf:properties>
<entry key="dataFormat" value="PAYLOAD"/>
</camel-cxf:properties>
</camel-cxf:cxfEndpoint>
<camelContext xmlns="http://camel.apache.org/schema/blueprint">
<route id="timerToLog">
<from uri="timer:foo?period=5000"/>
<to uri="mock:result"/>
</route>
</camelContext>
</blueprint>

I believe you're missing a schema reference and namespace: blueprint-cm. Try adding it like the example below.
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel-cxf="http://camel.apache.org/schema/cxf"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
xsi:schemaLocation="http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd
http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0 http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.0.0.xsd
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
<cm:property-placeholder persistent-id="com.example">
<cm:default-properties>
<property name="ws-logging" value="true"/>
</cm:default-properties>
</cm:property-placeholder>
</blueprint>

Related

bundle stays in GracePeriod status

I am trying to instantiate a "cxf:cxfEndpoint" in my camel route. But the bundle stays in "GracePeriod" status with following log:
2016-11-10 11:03:07,598 | INFO | rint Extender: 1 | BlueprintContainerImpl | ? ? | 21 - org.apache.aries.blueprint.core - 1.4.2 | Bundle com.entreprise.example is waiting for namespace handlers [http://camel.apache.org/schema/blueprint]
And my camelContext.xml file is :
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
xmlns:jaxws="http://cxf.apache.org/blueprint/jaxws" xmlns:cxf="http://cxf.apache.org/blueprint/core"
xmlns:camel="http://camel.apache.org/schema/blueprint" xmlns:camelcxf="http://camel.apache.org/schema/blueprint/cxf"
xsi:schemaLocation=" http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://cxf.apache.org/blueprint/jaxws http://cxf.apache.org/schemas/blueprint/jaxws.xsd
http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd">
<camelcxf:cxfEndpoint id="fist"
serviceClass="com.entreprise.example.services.firstService"
address="http://localhost:8181/cxf/example/firstMsg">
<camelcxf:properties>
<entry key="dataFormat" value="POJO" />
<entry key="loggingFeatureEnabled" value="true" />
</camelcxf:properties>
</camelcxf:cxfEndpoint>
<camelcxf:cxfEndpoint id="second"
serviceClass="com.entreprise.example.services.secondService"
address="http://localhost:8181/cxf/example/secondMessage">
<camelcxf:properties>
<entry key="dataFormat" value="POJO" />
<entry key="loggingFeatureEnabled" value="true" />
</camelcxf:properties>
</camelcxf:cxfEndpoint>
<camelContext trace="false" id="example"
xmlns="http://camel.apache.org/schema/blueprint">
<route>
<from uri="cxf:bean:first" />
<to uri="cxf:bean:second" />
</route>
</camelContext>
Seems like you have really messed up with your blueprint schema declartions. Replace blueprint declaration with something like below
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:cxf="http://camel.apache.org/schema/blueprint/cxf"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
And use "cxf" instead of "camelcxf" as prefix for the Endpoint and Bean this will become more clear and redeable (though you are free to use any prefix you prefer to use).
Ok, to avoid confusion use as below, this will resolve the waiting for dependencies error:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.2.0"
xmlns:cxf="http://camel.apache.org/schema/blueprint/cxf" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
<cxf:cxfEndpoint id="fist"
serviceClass="com.entreprise.example.services.firstService" address="http://localhost:8181/cxf/example/firstMsg">
<cxf:properties>
<entry key="dataFormat" value="POJO" />
<entry key="loggingFeatureEnabled" value="true" />
</cxf:properties>
</cxf:cxfEndpoint>
<cxf:cxfEndpoint id="second"
serviceClass="com.entreprise.example.services.secondService" address="http://localhost:8181/cxf/example/secondMessage">
<cxf:properties>
<entry key="dataFormat" value="POJO" />
<entry key="loggingFeatureEnabled" value="true" />
</cxf:properties>
</cxf:cxfEndpoint>
<camelContext trace="false" id="example"
xmlns="http://camel.apache.org/schema/blueprint">
<route>
<from uri="cxf:bean:first" />
<to uri="cxf:bean:second" />
</route>
</blueprint>

what does different tags in the below camel-CXF does

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cxf="http://camel.apache.org/schema/cxf"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<!-- Defined the real JAXRS back end service -->
<jaxrs:server id="restService"
address="http://localhost:${CXFTestSupport.port2}/CxfRsRouterTest/rest"
staticSubresourceResolution="true">
<jaxrs:serviceBeans>
<ref bean="customerService"/>
</jaxrs:serviceBeans>
</jaxrs:server>
<bean id="jsonProvider" class="org.apache.cxf.jaxrs.provider.json.JSONProvider"/>
<bean id="customerService" class="org.apache.camel.component.cxf.jaxrs.testbean.CustomerService" />
<!-- Defined the server endpoint to create the cxf-rs consumer -->
<cxf:rsServer id="rsServer" address="http://localhost:${CXFTestSupport.port1}/CxfRsRouterTest/route"
serviceClass="org.apache.camel.component.cxf.jaxrs.testbean.CustomerService"
loggingFeatureEnabled="true" loggingSizeLimit="20" skipFaultLogging="true">
<cxf:providers>
<ref bean="jsonProvider"/>
</cxf:providers>
</cxf:rsServer>
<!-- Defined the client endpoint to create the cxf-rs consumer -->
<cxf:rsClient id="rsClient" address="http://localhost:${CXFTestSupport.port2}/CxfRsRouterTest/rest"
serviceClass="org.apache.camel.component.cxf.jaxrs.testbean.CustomerService"
loggingFeatureEnabled="true" skipFaultLogging="true">
<cxf:providers>
<ref bean="jsonProvider"/>
</cxf:providers>
</cxf:rsClient>
<!-- The camel route context -->
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<route>
<!-- Just need to ignoreDeleteMethodMessageBody -->
<from uri="cxfrs://bean://rsServer"/>
<to uri="log:body?level=INFO"/>
<to uri="cxfrs://bean://rsClient?ignoreDeleteMethodMessageBody=true"/>
</route>
</camelContext>
</beans>
In the Camel Docs they say that cxf:rsServer is a REST Consumer where as cxf:rsClient is a REST producer but the code seems to do vice-versa.
Also i want to understand the difference between Jaxrs tag and cxf:rsserver and cxf:rsclient tags.
jaxrs:server : create a basic endpoint service.
cxf:rsServer : Is a camel component to create REST endpoint. It will turn a request into a normal Java object.
cxf:rsClient : Do the opposite of rsServer, it turn a java object to a REST request.
<camelContext>
<route>
<from uri="cxfrs://bean://rsServer" />
<to uri="log:body?level=INFO" />
<to uri="cxfrs://bean://..=true" />
</route>
</camelContext>
If we take a look to the code example, we see that this is a proxy. We received a REST request, we log it and then forward it.
<cxf:rsServer id="rsServer" address="http://localhost:${CXFTestSupport.port1}/CxfRsRouterTest/route"
serviceClass="org.apache.camel.component.cxf.jaxrs.testbean.CustomerService"
loggingFeatureEnabled="true" loggingSizeLimit="20" skipFaultLogging="true">
<cxf:providers>
<ref bean="jsonProvider"/>
</cxf:providers>
</cxf:rsServer>
<cxf:rsClient id="rsClient" address="http://localhost:${CXFTestSupport.port2}/CxfRsRouterTest/rest"
serviceClass="org.apache.camel.component.cxf.jaxrs.testbean.CustomerService"
loggingFeatureEnabled="true" skipFaultLogging="true">
<cxf:providers>
<ref bean="jsonProvider"/>
</cxf:providers>
</cxf:rsClient>
Theses tags is for configure your cxf component outside from the camel-route.
Hope this help.

Parameter dataFormatType is a mandatory field and cannot be empty. Please check the properties view for more details

how to solve this problem.i am beginner " jboss middleware"
http://i.stack.imgur.com/d4STG.png
Parameter dataFormatType is a mandatory field and cannot be empty. Please check the properties view for more details
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:camel="http://camel.apache.org/schema/blueprint"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
<!-- this is the JDBC data source Config for postgresql database -->
<bean class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" id="dataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/demo"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- configure the Camel SQL component to use the JDBC data source -->
<bean class="org.apache.camel.component.sql.SqlComponent" id="sql">
<property name="dataSource" ref="dataSource"/>
</bean>
<camelContext id="CustInfoContext" trace="false" xmlns="http://camel.apache.org/schema/blueprint">
<propertyPlaceholder id="properties" location="classpath:sql.properties"/>
<route customId="true" id="custinfoRoute">
<from id="_from1" uri="activemq:queue:customer"/>
<unmarshal id="_unmarshal1">
<jaxb contextPath="org.blogdemo.homeloan.model"
partClass="org.blogdemo.homeloan.model.CustInfo" prettyPrint="true"/>
</unmarshal>
<setHeader headerName="custNationalID" id="_setHeader1">
<simple>${body.nationalID}</simple>
</setHeader>
<setHeader headerName="firstName" id="_setHeader2">
<simple>${body.firstName}</simple>
</setHeader>
<setHeader headerName="lastName" id="_setHeader3">
<simple>${body.lastName}</simple>
</setHeader>
<setHeader headerName="age" id="_setHeader4">
<simple>${body.age}</simple>
</setHeader>
<setHeader headerName="occupation" id="_setHeader5">
<simple>${body.occupation}</simple>
</setHeader>
<to id="_to1" uri="sql:{{sql.insertCustInfo}}"/>
</route>
</camelContext>
So it seems that is a problem in the Beta1 version of the tooling. In the latest sources I can't reproduce this issue. See attached screenshots. I'd suggest to upgrade to the latest version as soon as it is released.

Camel integration with existing web application

I have a web application providing rest full service and another standalone (jar) application doing soap request response (using camel)
Can someone give me pointers to me for how to integrate the two applications
Specifically around how to kick camel routes when war file is deployed in tomcat, and how to re-run the routes when a specific HTTP request arrives.
I am using camel DSL (xml) and spring.
UPDATE 1:
I have followed this
Checked that web.xml has following lines:
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.mycompany.server.Binder</param-value>
</context-param>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j.properties</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Created a /WEB-INF/applicationContext.xml file and put all my routes and beans in it (btw I have beans.xml file as well in src/main/resources which is getting read by spring).
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns:camel="http://camel.apache.org/schema/spring"
xmlns:cxf="http://camel.apache.org/schema/cxf"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
">
<!-- Camel applicationContext -->
<!-- this import needed to bring in CXF classes -->
<import resource="classpath:META-INF/cxf/cxf.xml" />
<bean id="properties" class="org.apache.camel.component.properties.PropertiesComponent">
<property name="location" value="classpath:${env}/my.properties" />
</bean>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:${env}/my.properties</value>
</list>
</property>
</bean>
<camel:camelContext id="camelContext">
<camel:contextScan/>
<camel:template id="serviceConsumerTemplate" defaultEndpoint="direct:start" />
<camel:threadPoolProfile defaultProfile="true" id="defaultThreadPool" poolSize="10" maxPoolSize="15" />
<camel:route id="serviceGetAccount">
<camel:from uri="timer://kickoff?repeatCount=1"/>
<camel:to uri="bean:serviceGetAccountProcessor" />
<camel:to uri="bean:serviceRequestHeaderCreator" />
<camel:to uri="cxf:bean:serviceGetAccountEndpoint?dataFormat=POJO" />
<camel:to uri="bean:serviceGetAccountResponseProcessor" />
</camel:route>
</camel:camelContext>
<bean id="serviceRequestHeaderCreator" class="com.mycompany.service.soap.SOARequestHeaderCreator">
<property name="serviceName" value="service" />
<property name="spnValue" value="${nj.spn}" />
<property name="securityTokenEnabled" value="true" />
<property name="sendingApplication" value="NJ SERVICE" />
<property name="serviceVersion" value="3.0.2" />
<property name="sendingHost" ref="localHostName"/>
</bean>
<cxf:cxfEndpoint id="serviceGetAccountEndpoint"
address="${request.endpoint}/serviceAccountRequestResponsePT"
endpointName="s:serviceAccountRequestResponsePort"
serviceName="s:serviceAccountRequestResponseHTTP"
xmlns:s="http://soa.mycompany.com/services/service/wsdl/v3"
serviceClass="com.mycompany.services.service.wsdl.v3.serviceAccountRequestResponsePT"
loggingFeatureEnabled="true">
</cxf:cxfEndpoint>
<bean id="serviceGetAccountProcessor" class="com.mycompany.service.serviceGetAccountProcessor"/>
<bean id="serviceGetAccountResponseProcessor" class="com.mycompany.service.serviceGetAccountResponseProcessor"/>
</beans>
Up the logging level of log4j.logger.org.apache.camel=DEBUG
However do not see any camel log lines of routes starting.
Update 2:
I was not doing mvn clean generate-sources.
Once I started doing mvn clean and rebuilding the war file, camel kicked in.
Seems your spring context does not really fire. Make sure it is!
There should be some Spring info log events telling you about this.
Try adding this:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

Bean is initialized with #Controller but #RequestMapping doesn't get called

Below is my setup for the new Spring 3 annotation based controller:
// dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
<!--
The index controller.
-->
<bean name="indexController"
class="org.springframework.web.servlet.mvc.ParameterizableViewController"
p:viewName="index" />
<!-- Enables plain controllers -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="ignoreAcceptHeader" value="true" />
<property name="mediaTypes">
<map>
<entry key="xml" value="application/xml" />
<entry key="json" value="application/json" />
</map>
</property>
</bean>
<!-- Entity Property binding for webBindingInitializer -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="webBindingInitializer">
<bean class="org.opevel.web.BindingInitializer" />
</property>
</bean>
<context:component-scan base-package="org.opevel.web"/>
</beans>
// web.xml
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.htm</url-pattern>
<url-pattern>/auth</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
</web-app>
// Spring controller
package org.opevel.web;
#Controller
public class LoginGoogleController {
private static final Logger log = Logger.getLogger(LoginGoogleController.class.getName());
public LoginGoogleController() {
log.info("constructing LoginGoogleController");
}
#RequestMapping(value="/auth", method=RequestMethod.GET)
public String doGet(HttpServletRequest request, HttpServletResponse response) throws Exception {
return "redirect:index";
}
}
When I navigate to /auth, I get a 404. When I try to register the bean in the applicationContext like this:
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/auth">GoogleLoginService</prop>
</props>
</property>
<bean id="GoogleLoginService" class="org.opevel.web.LoginGoogleController" />
I get a BeanException stating that the bean is already registered at /logingoogle through ControllerClassNamehandlerMapping. I am using Spring 3.0.2 on Google App Engine.
Will appreciate some help.
I was able to fix this my removing both the ControllerClassNameHandlerMapping and SimpleUrlHandlerMapping beans from the application context file.
Regards y'all
That error is telling you that you don't need <bean id="GoogleLoginService" class="org.opevel.web.LoginGoogleController" /> in your applicationContext. Also you don't need <bean id="urlMapping">
#Controller creates a bean for you and #RequestMapping creates the URL mapping.

Resources