Hi I am trying to use Camel-SOAP component to unmarshal a soap message, sent using MQ.
But I can't figure out how to use ServiceInterfaceStrategy required by and SoapJaxbDataFormat
I'm using maven-jaxb2-plugin to generated my JAXB beans, using the provieded wsdl, xsd's.
What class should I use ?
And how do I generate it with maven-jaxb2-plugin ?
SoapJaxbDataFormat soap = new
SoapJaxbDataFormat("xx.xxx.service._201x._01._01.notification", new
ServiceInterfaceStrategy(WHAT_CLASS_TO_USE.class, false));
And how do I generate it with maven-jaxb2-plugin ?
To generate your class files using the plugin, try the following configuration:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.13.1</version>
<executions>
<execution>
<id>generate</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<schemaDirectory>src/test/resources/wsdl</schemaDirectory>
<generatePackage>org.tempuri.calculator.jaxb2</generatePackage>
<generateDirectory>src/test/java</generateDirectory>
<clearOutputDir>false</clearOutputDir>
<episode>false</episode>
<strict>true</strict>
<schemaIncludes>
<schemaInclude>*.wsdl</schemaInclude>
<schemaInclude>*.xsd</schemaInclude>
</schemaIncludes>
</configuration>
</execution>
</executions>
</plugin>
The maven command to generate the sources is: mvn generate-sources.
What class should I use ?
To use it in your routes, try the following:
protected SoapJaxbDataFormat createDataFormat() {
String jaxbPackage = Add.class.getPackage().getName();
ElementNameStrategy elStrat = new TypeNameStrategy();
SoapJaxbDataFormat answer = new SoapJaxbDataFormat(jaxbPackage, elStrat);
answer.setVersion("1.2");
return answer;
}
#Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
#Override
public void configure() throws Exception {
SoapJaxbDataFormat df = createDataFormat();
from("direct:start") //
.marshal(df) //
.to("mock:result");
}
};
}
The message should be a XML like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Envelope xmlns="http://www.w3.org/2003/05/soap-envelope" xmlns:ns2="http://tempuri.org/">
<Body>
<ns2:Add>
<ns2:intA>10</ns2:intA>
<ns2:intB>20</ns2:intB>
</ns2:Add>
</Body>
</Envelope>
The POJO counterpart (generated by the jaxb2 plugin):
package org.tempuri.calculator.jaxb2;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"intA",
"intB"
})
#XmlRootElement(name = "Add")
public class Add {
protected int intA;
protected int intB;
public int getIntA() {
return intA;
}
public void setIntA(int value) {
this.intA = value;
}
public int getIntB() {
return intB;
}
public void setIntB(int value) {
this.intB = value;
}
}
Don't forget to add the camel-soap dependency to your pom file:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-soap</artifactId>
</dependency>
The WSDL used by this example could be found here, based on this unit test.
Related
Below is my code, I am using command line tool, jax-rs, rest apis and java
I get this error: "SEVERE: MessageBodyWriter not found for media type = text/plain, type=class java.util.ArrayList, genericType=class java.util.ArrayList", when I go to localhost:8888/quotes after the command "mvn exec:java"
What am I doing wrong? I have a main class, Quote class, QuoteResource class, QuoteService class, quoteTest class, and pom.xml with the following code:
package edu.depaul.se457.bisbell;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.List;
/**
* Root resource (exposed at "quotes" path)
*/
#Path("quotes")
public class QuoteResource {
private QuoteService quoteService = new QuoteService();
#GET
#Produces(MediaType.TEXT_PLAIN)
public Response getAllQuotes() {
List<Quote> quotes = quoteService.getAllQuotes();
if (!quotes.isEmpty()){
return Response.ok(quotes).build();
}else{
return Response.status(Response.Status.NOT_FOUND).build();
}
}
#Path("/{id}")
#GET
#Produces(MediaType.TEXT_PLAIN)
//public int getQuoteByID(#PathParam("id") int id){
public Response getQuoteById(#PathParam("id") int id) throws NotFoundException{
Quote quote = quoteService.fetchBy(id);
if (quote.id.equals(null)) {
return Response.status(Response.Status.NOT_FOUND).build();
}else{
return Response.ok(quote).build();
}
}
#POST
#Produces(MediaType.TEXT_PLAIN)
#Consumes(MediaType.TEXT_PLAIN)
public Response createQuote(Quote quote){
boolean result = quoteService.create(quote);
if (result){
return Response.ok().status(Response.Status.CREATED).build();
}else{
return Response.notModified().build();
}
}
#PUT
#Path("/{id}")
#Consumes(MediaType.TEXT_PLAIN)
public Response updateQuote(#PathParam("id") int id, Quote quote) {
boolean result = quoteService.update(quote);
if (result) {
return Response.ok().status(Response.Status.NO_CONTENT).build();
} else {
return Response.notModified().build();
}
}
#Path("/{id}")
#DELETE
#Produces(MediaType.TEXT_PLAIN)
public Response deleteQuote(#PathParam("id") int id) {
boolean result = quoteService.delete(id);
if (result) {
return Response.ok().status(Response.Status.NO_CONTENT).build();
} else {
return Response.notModified().build();
}
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package edu.depaul.se457.bisbell;
/**
*
* #author bkisb
*/
public class Quote {
Integer id;
String quote;
public Quote() {
}
public Quote(String quote, int id){
super();
this.quote = quote;
this.id = id;
}
public String getQuote(){
return quote;
}
public void setQuote(String quote){
this.quote = quote;
}
public int getId(){
return id;
}
public void setId(int id){
this.id = id;
}
#Override
public String toString() {
return "Quote [id=" + id + "]";
}
boolean add(Quote quote) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
package edu.depaul.se457.bisbell;
import jakarta.ws.rs.NotFoundException;
import java.util.ArrayList;
import java.util.List;
/**
* Root resource (exposed at "quote" path)
*/
public class QuoteService {
/**
* Method handling HTTP GET requests. The returned object will be sent
* to the client as "text/plain" media type.
*
* #return String that will be returned as a text/plain response.
*/
List<Quote> quotes = new ArrayList<>();
public List<Quote> getAllQuotes() {
quotes.add(new Quote("Some Quote 1", 1));
quotes.add(new Quote("Some Quote 2", 2));
quotes.add(new Quote("Some Quote 3", 3));
quotes.add(new Quote("Some Quote 4", 4));
quotes.add(new Quote("Some Quote 5", 5));
return quotes;
}
//public int getQuoteByID(#PathParam("id") int id){
public Quote fetchBy(int id) throws NotFoundException{
for (Quote quote: getAllQuotes()) {
if (id == quote.getId()){
return quote;
}
else{
throw new NotFoundException("Resource not found with ID ::" + id);
}
}
return null;
}
public boolean create(Quote quote){
return quote.add(quote);
}
public boolean update(Quote quote){
for (Quote updateQuote: quotes) {
if (quote.getId() == (updateQuote.getId())){
quotes.remove(updateQuote);
quotes.add(quote);
return true;
}
}
return false;
}
public boolean delete(int id) throws NotFoundException {
for (Quote quote: quotes) {
if (quote.getId() == (id)) {
quotes.remove(quote);
return true;
}
}
return false;
}
}
package edu.depaul.se457.bisbell;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.WebTarget;
import org.glassfish.grizzly.http.server.HttpServer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class quoteTest {
private HttpServer server;
private WebTarget target;
#Before
public void setUp() throws Exception {
// start the server
server = Main.startServer();
// create the client
Client c = ClientBuilder.newClient();
// uncomment the following line if you want to enable
// support for JSON in the client (you also have to uncomment
// dependency on jersey-media-json module in pom.xml and Main.startServer())
// --
// c.configuration().enable(new org.glassfish.jersey.media.json.JsonJaxbFeature());
target = c.target(Main.BASE_URI);
}
#After
public void tearDown() throws Exception {
server.stop();
}
/**
* Test to see that the message "Got it!" is sent in the response.
*/
#Test
public void testGetIt() {
String responseMsg = target.path("quote").request().get(String.class);
assertEquals("Got It!", responseMsg);
}
}
package edu.depaul.se457.bisbell;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
import java.io.IOException;
import java.net.URI;
/**
* Main class.
*
*/
public class Main {
// Base URI the Grizzly HTTP server will listen on
public static final String BASE_URI = "http://localhost:8888/";
/**
* Starts Grizzly HTTP server exposing JAX-RS resources defined in this application.
* #return Grizzly HTTP server.
*/
public static HttpServer startServer() {
// create a resource config that scans for JAX-RS resources and providers
// in edu.depaul.se457.bisbell package
final ResourceConfig rc = new ResourceConfig().packages("edu.depaul.se457.bisbell");
// create and start a new instance of grizzly http server
// exposing the Jersey application at BASE_URI
return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
}
/**
* Main method.
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
final HttpServer server = startServer();
System.out.println(String.format("Jersey app started with endpoints available at "
+ "%s%nHit Ctrl-C to stop it...", BASE_URI));
System.in.read();
server.stop();
}
}
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>edu.depaul.se457.bisbell</groupId>
<artifactId>hw2</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>hw2</name>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
</dependency>
<!-- uncomment this to get JSON support:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-binding</artifactId>
</dependency>
-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<inherited>true</inherited>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>edu.depaul.se457.bisbell.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<jersey.version>3.0.4</jersey.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
I am using Spring Boot 2 to create web application and running the application using CommandLineRunner to connect PostgreSql database
1 . "LinkRepository" Interface:
package com.example.demo;
import org.springframework.data.repository.CrudRepository;
import com.example.entity.Link;
public interface LinkRepository extends CrudRepository<Link, Long> {
}
2. 'Link' Entity :
package com.example.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "link")
public class Link {
#Id
#GeneratedValue
#Column(name = "id")
private Long id;
#Column(name = "NAME")
private String name;
#Column(name = "url", unique = true)
private String url;
public Link(String name, String url) {
this.name = name;
this.url = url;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
3. Demo Application Config:
package com.example.demo;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import com.example.entity.Link;
#SpringBootApplication(scanBasePackages = { "com.example" })
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Bean
public CommandLineRunner demo(LinkRepository repository) {
// TODO Auto-generated method stub
return (args) -> {
repository.save(new Link("test", "link"));
for (Link linkrepo : repository.findAll()) {
System.out.println(linkrepo.getName());
}
};
}
}
4. Pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
5. Application.properties :
spring.datasource.url=jdbc:postgresql://localhost:5432/TestDb
spring.datasource.username=postgres
spring.datasource.password=root
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.hibernate.ddl-auto = create
spring.h2.console.enabled=true
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL95Dialect
I am getting following error :
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'demo' defined in com.example.demo.DemoApplication: Unsatisfied dependency expressed through method 'demo' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'linkRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class com.example.entity.Link
If you want to use CommandLineRunner, then that should be something like this:
`#SpringBootApplication(scanBasePackages = { "com.example" })
public class DemoApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
// TODO Auto-generated method stub
return (args) -> {
repository.save(new Link("test", "link"));
for (Link linkrepo : repository.findAll()) {
System.out.println(linkrepo.getName());
}
};
}
I've just prefer doing that like this:
1) Create a new class called for example DemoBootstrap
2) And it should be soemthing like this
#Component
public class DemoBootstrap implements ApplicationListener<ContextRefreshedEvent> {
private final LinkRepository categoryRepository;
public DemoBootstrap(LinkRepository linkRepository) {
this.linkRepository = linkRepository;
}
#Override
#Transactional
public void onApplicationEvent(ContextRefreshedEvent event) {
// Here add all links that should be saved
// for example
linkRepository.save(new Link("foo", "bar"));
linkRepository.save(new Link("foo2", "bar2"));
// etc
}
Add #EntityScan("com.example.entity") on DemoApplication class or move DemoApplication to 'com.example' package and then spring will scan all sub-packages.
i have a POJO class BookType as:
package com.jersey.series.json.service;
import java.util.HashMap;
import java.util.Set;
public class BookType {
#Override
public String toString() {
return "BookType [bookId=" + bookId + ", bookName=" + bookName + ", author=" + author + ", category=" + category
+ ", obj=" + obj + "]";
}
protected int bookId;
protected String bookName;
protected String author;
protected String category;
protected HashMap<String, Set<String>> obj = new HashMap<>();
public HashMap<String, Set<String>> getObj() {
return obj;
}
public void setObj(HashMap<String, Set<String>> obj) {
this.obj = obj;
}
public int getBookId() {
return bookId;
}
public void setBookId(int value) {
this.bookId = value;
}
public String getBookName() {
return bookName;
}
public void setBookName(String value) {
this.bookName = value;
}
public String getAuthor() {
return author;
}
public void setAuthor(String value) {
this.author = value;
}
public String getCategory() {
return category;
}
public void setCategory(String value) {
this.category = value;
}
}
And a rest Service :
package com.jersey.series.json.service;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
#Path("/bookservice")
public class BookServiceImpl implements IBookService {
#POST
#Path("addbookandreturnjson")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public BookType saveAndReturnBookInfojson(BookType bookType) {
return bookType;
}
}
i ma making this call using PostMan:
http://localhost:8080/Jersey-JSON-IO/rest/bookservice/addbookandreturnjson
this is my message body with type application Json
{"bookId":5,"bookName":"abc","author":"saurabh","category":"Test","obj":{"1":["abc","xyz"]}}
Service is receiving everything correct except for the "obj" field where am i doing wrong or what i need to do.I am using Glassfish 4.1.1 as web container.Here is my pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>in.bench.resources</groupId>
<artifactId>Jersey-JSON-IO</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>Jersey-JSON-IO</name>
<description>Jersey web service using JSON (Jackson parser) as request/response</description>
<!-- https://jersey.java.net/documentation/latest/media.html#json.jackson -->
<!-- Jersey repository -->
<repositories>
<repository>
<id>snapshot-repository.java.net</id>
<name>Java.net Snapshot Repository for Maven</name>
<url>https://maven.java.net/content/repositories/snapshots/</url>
<layout>default</layout>
</repository>
<repository>
<id>prime-repo</id>
<name>PrimeFaces Maven Repository</name>
<url>http://repository.primefaces.org</url>
<layout>default</layout>
</repository>
</repositories>
<properties>
<jersey.version>2.12</jersey.version>
<jersey.scope>compile</jersey.scope>
<compileSource>1.7</compileSource>
<maven.compiler.target>1.7</maven.compiler.target>
<maven.compiler.source>1.7</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<finalName>Jersey-JSON-IO</finalName>
<!-- maven compiler plugin -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>${jersey.version}</version>
<scope>${jersey.scope}</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
<scope>${jersey.scope}</scope>
</dependency>
</dependencies>
I've been trying to start and stop Jetty automatically in mvn clean install phase for my unit tests. The annoying thing is when I deploy my war file in JBoss all the tests are working fine, however, when I try to use maven-jetty-plugin I have a Connection refuse: connect error. I'm sure about that Jetty starts but doesnt recognize the URLs so that it can't establish the connection.
pom.xml
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>8.1.13.v20130916</version>
<configuration>
<webApp>
<contextPath>/</contextPath>
</webApp>
<scanIntervalSeconds>10</scanIntervalSeconds>
<stopKey>foo</stopKey>
<stopPort>9999</stopPort>
</configuration>
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<scanIntervalSeconds>0</scanIntervalSeconds>
<daemon>true</daemon>
</configuration>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
default web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app 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_3_0.xsd"
version="3.0">
</web-app>
and my other classes
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import com.buraktas.resource.DefaultBookResource;
#ApplicationPath("/services")
public class BaseApplication extends Application {
private Set<Object> singletons = new HashSet<Object>();
public BaseApplication() {
singletons.add(new DefaultBookResource());
}
#Override
public Set<Object> getSingletons() {
return singletons;
}
}
entity class
public class BookEntity {
private int id;
private String title;
private String author;
private double price;
... setters and getters
}
resource interface
#Path("/book-service")
public interface BookResource {
#POST
#Path("/create")
#Consumes("application/json")
#Produces("application/json")
public BookEntity createBook(BookEntity bookEntity);
}
and the implementation of it
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import com.buraktas.entity.BookEntity;
public class DefaultBookResource implements BookResource {
private Map<Integer, BookEntity> list = new HashMap<Integer, BookEntity>();
private AtomicInteger idCounter = new AtomicInteger();
#Override
public BookEntity createBook(BookEntity bookEntity) {
bookEntity.setId(idCounter.getAndIncrement());
list.put(bookEntity.getId(), bookEntity);
return bookEntity;
}
}
finally test class
public class TestClass {
private static final String POST_INPUT = "{\"title\" : \"LOTR\",\"author\" : \"J.K.Rowling\",\"price\" : 12.99}";
private static Client client;
#Before
public void setUp() {
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
client = Client.create(clientConfig);
}
#After
public void close() {
client.destroy();
}
#Test
public void testCreateSuccess() throws Exception {
WebResource webResourcePost = client.resource("http://localhost:8080/jersey-rest-client/services/book-service/create");
ClientResponse response = webResourcePost.accept("application/json").type("application/json").post(ClientResponse.class, POST_INPUT);
BookEntity responseEntity = response.getEntity(BookEntity.class);
assertEquals(200, response.getStatus());
assertEquals("LOTR", responseEntity.getTitle());
assertEquals("J.K.Rowling", responseEntity.getAuthor());
assertEquals(12.99, responseEntity.getPrice(), 0.0001);
}
}
Also you can find the whole implementation from here
https://github.com/flexelem/jersey-client-example
I will appreciate for every response. Thanks anyway
I need to use custom type, e.g., LunarDate, in my Mojo object:
class MyMojo extends AbstractMojo {
/** #parameter */
LunarDate lunarDate;
}
And I want to configure the parameter in <configuration> section in pom.xml.
<configuration>
<lunarDate>丁丑年二月初四</lunarDate>
</configuration>
(The type LunarDate is just an example to illustrate the question)
I've already had the type converters, but how to enable them?
DefaultBeanConfigurator is responsible for using DefaultConverterLookup, and it instantiates it directly without using the Plexus Container.
You could I suppose copy and modify it in a build extension, but registering your copy via #Component(role=BeanConfigurator.class) will likely have no effect; I have tried replacing standard Maven components in the past from build extensions and been told on maven-dev that it is not possible.
You could look up the default BeanConfigurator and use reflection to get its ConverterLookup converterLookup field, then call registerConverter with your custom convertor, but this would be fragile.
Probably best is to just give up, declare your Mojo parameter to be of type String, and do the conversion explicitly in execute.
I was able to solve this by defining a ConfigurationConverter (my target
type is a AnyLicenseInfo):
#NoArgsConstructor #ToString
public class LicenseConverter extends AbstractBasicConverter {
private static final Class<?> TYPE = AnyLicenseInfo.class;
#Override
public boolean canConvert(Class<?> type) { return type.equals(TYPE); }
#Override
public Object fromString(String string) throws ComponentConfigurationException {
Object object = null;
try {
object =
TYPE.cast(LicenseInfoFactory.parseSPDXLicenseString(string));
} catch (Exception exception) {
String message =
"Unable to convert '" + string + "' to " + TYPE.getName();
throw new ComponentConfigurationException(message, exception);
}
return object;
}
}
Registering it with a custom ComponentConfigurator:
#Named("license-mojo-component-configurator")
#NoArgsConstructor #ToString #Slf4j
public class LicenseMojoComponentConfigurator extends BasicComponentConfigurator {
#PostConstruct
public void init() {
converterLookup.registerConverter(new LicenseConverter());
}
#PreDestroy
public void destroy() { }
}
And then specifying the configurator in the #Mogo annotation:
#Mojo(name = "generate-license-resources",
configurator = "license-mojo-component-configurator",
requiresDependencyResolution = TEST,
defaultPhase = GENERATE_RESOURCES, requiresProject = true)
#NoArgsConstructor #ToString #Slf4j
public class GenerateLicenseResourcesMojo extends AbstractLicenseMojo {
For newer Maven (tested with Maven 3.3.1) you can now subclass BasicComponentConfigurator to access the DefaultConverterLookup as a member variable:
#Component(role = ComponentConfigurator.class, hint = "basic")
public class ExtendedComponentRegistrator
extends BasicComponentConfigurator
implements Initializable {
#Override
public void initialize() throws InitializationException {
converterLookup.registerConverter(new MyCustomConverter());
}
}
Then in the pom.xml enable the generation of plexus meta data:
<plugin>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-component-metadata</artifactId>
<executions>
<execution>
<goals>
<goal>generate-metadata</goal>
</goals>
</execution>
</executions>
</plugin>