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;
}
}
Related
Im working on a spring boot application for rest service with using spring data jpa. I followed instructors and read much answers but I couldn't fix my rest service.
Here is application.class
package tr.kasim.Application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#SpringBootApplication
#EnableJpaRepositories("tr.kasim.Dao")
#EntityScan("tr.kasim.Model")
#ComponentScan({"tr.kasim.Service", "tr.kasim.Application" })
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Here is `restcontroller.class
package tr.kasim.Controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import tr.kasim.Service.PersonelService;
import tr.kasim.Model.Personel;
#RestController
public class STRestController {
#Autowired
public PersonelService personelService;
#RequestMapping(value = "/api/personels", method = RequestMethod.GET)
public ResponseEntity<List<Personel>> getPersonels(){
List<Personel> personels = personelService.findAll();
return ResponseEntity.ok().body(personels);
}
}
`
Here is Service.class`
package tr.kasim.Service;
import java.util.List;
import tr.kasim.Model.Personel;
public interface PersonelService {
List<Personel> findAll();
}
`
Here is ServiceImplemantion.class
package tr.kasim.Service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tr.kasim.Dao.PersonelDao;
import tr.kasim.Model.Personel;
#Service
public class PersonelServiceImpl implements PersonelService {
#Autowired
private PersonelDao personelDao;
#Override
#Transactional
public List<Personel> findAll() {
return personelDao.findAll();
}
}
Here is Dao.class
package tr.kasim.Dao;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import tr.kasim.Model.Personel;
#Repository
public interface PersonelDao extends JpaRepository<Personel, Long> {
List<Personel> findAll();
}
Lastly here is my application.properties
#MySql Connection
spring.datasource.url=jdbc:mysql://localhost:3306/exampleproject?verifyServerCertificate=false&useSSL=true
spring.datasource.username=root
spring.datasource.password=*******
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#Jpa/Hibernate
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
#Logging
logging.file=staffTracking.log
logging.level.org.springframework.web=debug
Im not sure about componentScan. When I read answers I discovered someone mentioned about it but I tried and I got still nothing. Please show me where I failed. Best Regards.
I updated Application.class, now I can deploying project but rest service not working still.
How did you try ComponentScan? The issue here seems that you have a package structure like this:
tr.kasim.Application
- Application.java
tr.kasim.Service
- PersonelService.java
- PersonelServiceImpl.java
tr.kasim.Dao
- PersonelDao.java
Now since, the mainClass is in tr.kasim.Application it would scan for bean definitions inside that package (or a sub-package in tr.kasim.Application). So,
either you move the mainClass out to a parent-package like tr.kasim, or
use #ComponentScan({ "tr.kasim.Dao", "tr.kasim.Service", "tr.kasim.Application" }) and so on.
-- Update --
Based on the discussion so far, I'd suggest taking the first option as that reduces the effort to manually enable scan for entity, repository, etc.
I am learning REST web services with JAX-RS.
below are the two classes I have written :
package com.vitp.app;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("/api")
public class MyApp extends Application {
}
And
package com.vitp.rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("/test")
public class Test {
#GET
#Produces(MediaType.TEXT_PLAIN)
#Path("/t")
public String doTest()
{
return "test success";
}
}
I am deploying this WebApp with Tomcat v7.0.
when I trying to access URL: http://localhost:8080/RestAdvance/api/test/t I get 404 error.
Not able to figure out what is going wrong here.
You need to extend ResourceConfig and register your Test class:
#ApplicationPath("/api")
public class MyApp extends ResourceConfig {
public MyApp () {
register(Test.class);
}
}
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>
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>
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 :)