How to invoke restful webservice using apache camel - rest

my restful service is
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import org.hibernate.Query;
import org.hibernate.Session;
import org.json.JSONArray;
#Path("/detailsservice/")
public class DetailsService {
Dao d=new Dao();
#GET
#Path("/details/{id}/")
#Produces("text/xml")
public Details getDetails(#PathParam("id") String id) {
Session hs = d.dao();
Details de = (Details) hs.load(Details.class,new Integer(id));
return de;
}
}
I exposed this service on the web by using jetty server
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
public class Server {
protected Server() throws Exception {
JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
sf.setResourceClasses(DetailsService.class);
System.out.println("two");
sf.setResourceProvider(DetailsService.class, new SingletonResourceProvider(new DetailsService()));
sf.setAddress("http://localhost:9000/");
sf.create();
}
public static void main(String args[]) throws Exception {
new Server();
System.out.println("Server ready...");
Thread.sleep(5 * 6000 * 1000);
System.out.println("Server exiting");
System.exit(0);
}
}
How can i invoke this service by using apache camel.
please explain me in detail because i am new to the camel.
Thanks in advance

You can use the http4 component:
<route>
<from uri="http4://localhost:9000/detailsservice/details/1234" />
<!-- add your processors here -->
<to uri="..." />
</route>

Related

Facing HTTP 415 Unsupported Media Type from JAX-RS client when using MessageBodyReader

I am new to RESTFul wit JAX-RS and learning. I am facing problem only when i request from JAX-RS client application. Its working fine from post plugin. But when i am changing the #Consumes("myformat/xml") with "application/xml" then its working. Below is the code.
MessageBodyReader:
package com.memorynotfound.jaxrs.chunked;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import javax.ws.rs.Consumes;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Provider;
#Provider
#Consumes("myformat/xml")
public class UserMessageBodyReader implements MessageBodyReader<User> {
public boolean isReadable(Class<?> arg0, Type arg1, Annotation[] arg2, MediaType arg3) {
if (arg0.equals(User.class))
return true;
else
return false;
}
public User readFrom(Class<User> arg0, Type arg1, Annotation[] arg2, MediaType arg3,
MultivaluedMap<String, String> arg4, InputStream arg5) throws IOException, WebApplicationException {
return new User(1, "Jphn Doe");
}
}
Resource:
package com.memorynotfound.jaxrs.chunked;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
#Path("/users")
public class UserResource {
#POST
#Consumes("myformat/xml")
public User getUser(User user) {
return user;
}
}
Client code:
package com.restfulexample.client.messagebodyreader;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
public class MessageBodyReader {
public static void main(String[] args) {
Client client = ClientBuilder.newClient();
User user = new User(1, "Jphn Doe");
User postedUser = client.target("http://localhost:9090/message-body-reader/api/users").request("myformat/xml")
.post(Entity.xml(user), User.class);
System.out.println(postedUser.getId() + " " + postedUser.getName());
}
}
Found the solution with the below code...
Client client = ClientBuilder.newClient().register(UserMessageBodyReader.class)
.register(UserMessageBodyWriter.class);
We have to register both MessageBodyReader and Writer with the client.

Spring Security 403 http status

I am implementing Spring Security on a Spring Boot 2.0.1 project.
I have some web services that used to work fine before Spring Security implementation. But now, they don't.
This is the error message displayed in REST client.
{
"timestamp": "2018-07-27T11:14:40.080+0000",
"status": 403,
"error": "Forbidden",
"message": "Access Denied",
"path": "/lsm/notification/getCurrentUserNotifications"
}
and the same error on google chrome :
Below is the controller listing the services:
package com.sap.lsm.web;
import java.util.List;
import java.util.Random;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.sap.lsm.dao.NotifiedUserRepository;
import com.sap.lsm.dao.UserNotificationRepository;
import com.sap.lsm.entities.NotifiedUser;
import com.sap.lsm.entities.UserNotification;
import com.sap.lsm.service.UserNotificationService;
#RestController
public class UserNotificationController {
#Autowired
private UserNotificationService userNotificationService;
#Autowired
private UserNotificationRepository userNotificationRepository;
#RequestMapping(value="/notification/getCurrentUserNotifications", method=RequestMethod.GET)
public List<UserNotification> getCurrentUserNotifs() {
return userNotificationService.getCurrentUserAllNotifications();
}
#RequestMapping(value="/notification/getCurrentUserNotSeenNotifications", method=RequestMethod.GET)
public List<UserNotification> getCurrentUserNotSeenNotifs() {
return userNotificationService.getCurrentUserNotSeenNotifications();
}
#RequestMapping(value="/notification/deleteNotification/{id}", method=RequestMethod.DELETE)
public void deleteNotification(#PathVariable("id") Long id){
userNotificationService.deleteNotification(id);
}
#RequestMapping(value="/notification/getNotification/{id}", method=RequestMethod.GET)
public UserNotification getNotification(#PathVariable("id") Long id) {
UserNotification notification = this.userNotificationService.getNotification(id);
if(!notification.equals(null)) {
notification.setStatus("seen");
userNotificationRepository.save(notification);
}
return notification;
}
#RequestMapping(value="/notification/markCurrentUserNotificationsAsSeen", method=RequestMethod.GET)
public void markCurrentUserNotificationsAsSeen() {
userNotificationService.markAllNotificationsAsSeen();
}
}
And this is the Spring Security Config :
package com.sap.lsm.config;
import javax.servlet.Filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
#EnableGlobalMethodSecurity(prePostEnabled=true)
#EnableWebSecurity
#Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private RequestFilter requestFilter;
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
public SpringSecurityConfig(UserDetailsService userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder) {
this.userDetailsService = userDetailsService;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
public void setUserDetailsService(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
public void setbCryptPasswordEncoder(BCryptPasswordEncoder bCryptPasswordEncoder) {
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.cors()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.logout().deleteCookies("JSESSIONID").invalidateHttpSession(true)
.and()
.authorizeRequests()
.antMatchers("/lsm/listCustomers").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/addCustomer").hasAnyAuthority("CONSULTANT")
.antMatchers("/lsm/getAllCustomers").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/getOldCustomers").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/getCustomers").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/getCustomer/*").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/deleteCustomer/*").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/cancelCustomer/*").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/restoreCustomer/*").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/updateCustomer/*").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/getLSMUsers").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/addLSMUser").hasAnyAuthority("ADMIN")
.antMatchers("/lsm/getLSMUser/*").hasAnyAuthority("ADMIN")
.antMatchers("/lsm/deleteLSMUser/*").hasAnyAuthority("ADMIN")
.antMatchers("/lsm/cancelLSMUser/*").hasAnyAuthority("ADMIN")
.antMatchers("/lsm/restoreLSMUser/*").hasAnyAuthority("ADMIN")
.antMatchers("/lsm/updateLSMUser/*").hasAnyAuthority("ADMIN")
.antMatchers("/lsm/notification/getCurrentUserNotifications/*").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/notification/getCurrentUserNotSeenNotifications/*").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/notification/deleteNotification/*").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/notification/getNotification/*").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/notification/markCurrentUserNotificationsAsSeen/*").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/assets/**","/login","/*").permitAll()
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
.addFilterBefore((Filter) new JWTAuthorizationFilter(),UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(requestFilter, ChannelProcessingFilter.class);
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
}
If you need JWT authentication and authorization filters, i'll post them later on .
Please help me,
Thanks
** update **
The role of the connected user is ADMIN.
The path /lsm is declared as property in the pom.xml as follows:
<m2eclipse.wtp.contextRoot>/lsm</m2eclipse.wtp.contextRoot>
This root path is used to run the application under Jenkins (integration server)

swagger documentation for hybris

I need to generate rest api documentation using swagger for hybris.
I got Kongchan's sample pom.xml, but I couldn't really modify to match with hybris code. Can anyone pls provide me sample pom.xml for hybris or any links or documents.
Find the Wiki for generating Hybris API Documentation with Swagger
Edit:
You can follow spring-xml-swagger example to integrate it with Hybris using XML configuration. Also, this and this posts will help you.
Here is the class I use for OCC (tested on hybris 6.6)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* #author ajaninmanificat Spring configuration for swagger. Only available if spring profile "swagger" is enabled.
*
*/
#Configuration
#EnableSwagger2
#Profile("swagger")
public class SwaggerConfig extends WebMvcConfigurationSupport
{
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry)
{
registry.addResourceHandler("**/swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
#Bean
public Docket api()
{
final ApiInfo apiInfo = new ApiInfoBuilder().title("OCC API documentation")
.description("This document contains the generated API documentation for Omni Commerce Connect v2.")
.version("Version v2").build();
return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.any()).paths(PathSelectors.any())
.build().apiInfo(apiInfo).useDefaultResponseMessages(false).enableUrlTemplating(true);
}
}
To enable Swagger you have to set this property : spring.profiles.active=swagger. The idea is to prevent Swagger from being loaded in production.
To avoid any troubles with BaseSiteMatchingFilter I suggest to create a subclass IgnorableBaseSiteMatchingFilter
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class IgnorableBaseSiteMatchingFilter extends BaseSiteMatchingFilter
{
private String regexpIgnore;
#Override
protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response,
final FilterChain filterChain) throws ServletException, IOException
{
final boolean shouldIgnore = (regexpIgnore != null) && matchesUrl(request, regexpIgnore);
if (shouldIgnore)
{
filterChain.doFilter(request, response);
}
else
{
// Is not ignored, call the real stuff
super.doFilterInternal(request, response, filterChain);
}
}
public void setRegexpIgnore(final String regexpIgnore)
{
this.regexpIgnore = regexpIgnore;
}
}
And the bean declaration looks like this :
<alias alias="baseSiteMatchingFilter" name="myBaseSiteMatchingFilter" />
<bean id="myBaseSiteMatchingFilter" class="mypackage.IgnorableBaseSiteMatchingFilter" parent="defaultBaseSiteMatchingFilter">
<property name="regexpIgnore" value="(swagger|api-docs|info|login|logout|/health/|/css/|/img/|/js/|/font-awesome/|/bootstrap/|/assets/|/node_modules/)" />
</bean>

JAX-RS REST service implementation in EJB J2EE

Looking for a an example of using JAX-RS to implement an EJB 3 REST service. Would like to have the transactional functionality of EJB and be able to call the EJB from other J2EE apps as well as from AJAX apps (web, mobile, etc).
Service implemented as a stateless session bean. Used a singleton bean to simulate a DAO for illustration purposes.
 
PUT example:
http://mydomain/MyApp/rest/carbean/savecarorder
ContentType:    application/json
JSON:                    {"equipmentId":"570674","status":"L","operation":"PS"}
 
GET example (after the PUT operation to insert or update):
http://mydomain/MyApp/rest/carbean/getcarorder?equipmentId=570674
Results:                {"status":"L","operation":"PS","equipmentId":"570674"}
package com.samnunnally.services;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import com.samnunnally.CarManager;
import com.samnunnally.CarOrder;
/**
* Session Bean implementation class CarService
*/
#Stateless(mappedName = "ejb/CarService")
#LocalBean
#Path ("/carbean")
public class CarService {
#EJB
CarManager carManager;
#GET
#Produces({ MediaType.APPLICATION_JSON })
#Path("/getcarorder")
public CarOrder getCar(#QueryParam("equipmentId") String equipmentId) {
return carManager.getCarOrder(equipmentId);
}
#Path("/savecarorder")
#PUT
#Consumes({ "application/xml", "application/json" })
public String saveCarOrder(CarOrder carOrder) {
carManager.saveCarOrder(carOrder);
return "true";
}
}
This needed to added to the web.xml file of the war file in the ear:
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Manager to simulate data layer
package com.samnunnally.managers;
import java.util.HashMap;
import java.util.Map;
import javax.ejb.LocalBean;
import javax.ejb.Singleton;
import com.samnunnally.model.CarOrder;
/**
* Session Bean implementation class CarManager
*
* #author Sam Nunnally
*
*/
#Singleton(mappedName = "ejb/CarManager")
#LocalBean
public class CarManager {
/*
* this should be a database of some sort
*/
private Map<String, CarOrder> carOrders = null;
public CarOrder getCarOrder(String equipmentId) {
return getCarOrders().get(equipmentId);
}
public void saveCarOrder(CarOrder carOrder) {
getCarOrders().put(carOrder.getEquipmentId(), carOrder);
}
private Map<String, CarOrder> getCarOrders(){
if(carOrders == null){
carOrders = new HashMap<String, CarOrder>();
}
return carOrders;
}
}

HTTP Basic Authentication in Restlet with a JAXRS Application?

I'm trying to authenticate access to all resources on my server via HTTP Basic authentication. Currently, my setup looks like this when starting the server:
this.component = new Component();
this.server = this.component.getServers().add(Protocol.HTTP, 8118);
JaxRsApplication application = new JaxRsApplication(component.getContext()
.createChildContext());
application.add(new RestletApplication());
ChallengeAuthenticator authenticator = new ChallengeAuthenticator(
this.component.getContext(),
ChallengeScheme.HTTP_BASIC, "test");
authenticator.setVerifier(new ApplicationVerifier());
this.component.getDefaultHost().attachDefault(authenticator);
this.component.getDefaultHost().attach(application);
this.component.start();
Here's my RestletApplication:
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
public class RestletApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(TestResource.class);
return classes;
}
}
Here's my ApplicationVerifier:
import java.util.HashMap;
import java.util.Map;
import org.restlet.security.LocalVerifier;
public class ApplicationVerifier extends LocalVerifier {
private Map<String, char[]> localSecrets = new HashMap<String, char[]>();
public ApplicationVerifier() {
this.localSecrets.put("username", "password".toCharArray());
}
#Override
public char[] getLocalSecret(String key) {
if (this.localSecrets.containsKey(key))
return this.localSecrets.get(key);
return null;
}
}
Finally, here's my TestResource:
import java.util.*;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
#Path("test")
public class TestResource {
#GET
#Path("list")
public TestList getTestList() {
return makeTestList();
}
}
However, I'm not seeing any prompt or requirement for authentication when I try to access the resource. What am I doing wrong? I'm not having any issues with marshalling and unmarshalling items and I'm sure that my resource is getting hit with requests. What am I not doing right?
According to the JavaDocs for JaxRsApplication, an authenticator can be set using the following code before starting things up:
((JaxRsApplication)application).setGuard((Authenticator)authenticator);
Do that, and all requests will fly through your authenticator :)