Wildfly Swarm Bean Validation Custom constraint calls not - jax-rs

I'm trying to implement a REST Web Service using JAX-RS and Widlfly Swarm (2017.4.0 version) using JAX-RS Bean Validation.
Default bean validation annotations work as expected, but the custom constraints defined annotations seem to be ignored.
My (simplified) REST endpoint looks like that
#Path("/myservice")
#Produces({ MediaType.APPLICATION_JSON })
#Consumes({ MediaType.APPLICATION_JSON })
public class MyEndPoint {
#POST
#Path("/data")
public Response data(#CheckDate String date) {
return Response.ok().build();
}
}
The annotation for the validation constratint looks like
#Retention(RUNTIME)
#Target({ FIELD, PARAMETER })
#Constraint(validatedBy = CheckDateValidator.class)
public #interface CheckDate {
String message() default "Bad date format";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
The validator class "CheckDateValidator"
public class CheckDateValidator implements ConstraintValidator<CheckDate, String> {
public static final String dateFormat = "YYYYMMDD";
#Override
public void initialize(CheckDate constraintAnnotation) {
int i = 0;
}
#Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return validate(value);
}
private boolean validate(String dateString) {
boolean valid = true;
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
sdf.setLenient(false);
try {
sdf.parse(dateString.trim());
} catch (ParseException e) {
valid = false;
}
return valid;
}
}
Replacing the #CheckDate annotation by #Email default validator
#Path("/myservice")
#Produces({ MediaType.APPLICATION_JSON })
#Consumes({ MediaType.APPLICATION_JSON })
public class MyEndPoint {
#POST
#Path("/data")
public Response data(#EmailString date) {
return Response.ok().build();
}
}
The e-mail format validation is applied but with my custom constraint #CheckDate no validation is applied.
I think I've added the needed Wildfly Swarm fractions dependencies in the POM file
<dependencies>
<!-- Java EE 7 dependency -->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<!-- WildFly Swarm Fractions -->
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>jaxrs-jaxb</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>datasources</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${version.h2}</version>
</dependency>
<dependency>
<groupId>ParmaAlgorithmDatamodel</groupId>
<artifactId>ParmaAlgorithmDatamodel</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.systelabsw</groupId>
<artifactId>Connectors</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>swagger</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>swagger-webapp</artifactId>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.9</version>
</dependency>
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>jaxrs-validator</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>bean-validation</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>jaxrs-cdi</artifactId>
</dependency>
</dependencies>
I don't know if there is any extra configuration to be done or if I'm defining the custom constraint in a wrong way.
Any help would be appreciated

Related

How to trace message with camel-zipkin and camel-rabbitmq

I have implemented different microservice where internal communication is taking place by camel and rabbitMQ with different exchange and queue. I'm using camel-zipkin for tracing, and log4j2 for logging.
Ex:
Service1 Publish message to RabbitMQ ( i.e Exchange 1 -> Queue 1)
where Service2 Consume message
Service2 Publish message to RabbitMQ ( i.e Exchange 1 -> Queue 2)
where Service3 Consume message and so on.
I am using Springboot 1.5.12.RELEASE and Camel 2.21.5 version with the following dependencies (of camel):
camel-spring-boot-starter
camel-rabbitmq-starter
camel-core
camel-spring
camel-zipkin-starter
camel-test
camel-test-spring
I need suggestion for my two problems
span-id, trace-id are not getting printed in logs. I have necessary placeholders added in my log4j2.xml.
Whenever a message is sent to an exchange a unique span-id and trace-id is getting generated.
My Questions are :
Is it possible to have a unique traceID for entire data traverse from Service 1 to Service N.
How can I print span-id, trace-id to logs.
Sample Code :
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>1.5.12.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.camel</groupId>
<artifactId>example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>example</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<camel.version>2.21.5</camel.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!-- Camel Dependency -->
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-rabbitmq-starter</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-zipkin-starter</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-test</artifactId>
<version>${camel.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-test-spring</artifactId>
<version>${camel.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
SpringBoot Application
#SpringBootApplication
#CamelZipkin
public class ExampleApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleApplication.class, args);
}
}
RabbitMQConfig
#EnableRabbit
#Profile("default")
#Configuration
public class RabbitMQConfig {
#Value("${camel.component.rabbitmq.hostname}")
private String host;
#Value("${camel.component.rabbitmq.port-number:5672}")
private int port;
#Value("${camel.component.rabbitmq.username}")
private String username;
#Value("${camel.component.rabbitmq.password}")
private String password;
#Value("${camel.component.rabbitmq.vhost}")
private String virtualHost;
#Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host, port);
connectionFactory.setUsername(username);
connectionFactory.setPassword(password);
connectionFactory.setVirtualHost(virtualHost);
connectionFactory.setCacheMode(CacheMode.CONNECTION);
return connectionFactory;
}
#Bean
public Channel amqpChannel(ConnectionFactory connectionFactory) throws IOException {
Connection connection = connectionFactory.createConnection();
Channel channel = connection.createChannel(false);
Map<String, Object> args = new HashMap<>();
args.put("x-delayed-type", "direct");
channel.exchangeDeclare("example-service", "x-delayed-message", true, false, args);
return channel;
}
}
Controller adding message to queue
#RestController
public class MessageController {
private static final Logger log = LoggerFactory.getLogger(MessageController.class);
#Autowired
protected ProducerTemplate producer;
#PostMapping(value = "send/message")
public void sendMessageTopic(#RequestBody MessageDto message) {
log.debug("In controller sending message ");
producer.requestBody("rabbitmq:example-service?routingKey=example-service.ers.send&queue=example-service-ers-send", message);
}
}
RouteBuilder
#Component
public class AppRouteBuilder extends RouteBuilder {
#Autowired
private MessageActivity messageActivity;
#Autowired
private SmsActivity smsActivity;
#Override
public void configure() throws Exception {
// TODO Auto-generated method stub
from("rabbitmq:example-service?routingKey=example-service.ers.send&queue=example-service-ers-send")
.bean(messageActivity).end();
from("rabbitmq:example-service?routingKey=example-service.sms.send&queue=example-service-sms-send")
.bean(smsActivity).end();
}
}
MessageActivity
#Service
public class MessageActivity {
private static final Logger log = LoggerFactory.getLogger(MessageActivity.class);
#Autowired
protected ProducerTemplate producer;
public void doAction() {
log.debug("Hello in message activity ");
producer.requestBody("rabbitmq:example-service?routingKey=example-service.sms.send&queue=example-service-sms-send", "Hello from message");
}
}
SmsActivity
#Service
public class SmsActivity {
private static final Logger log = LoggerFactory.getLogger(SmsActivity.class);
public void doAction() {
log.debug("Hello in sms activity ");
}
}
Output
2019-12-03T21:07:54.316+07:00|2|INFO|example-service|,,|50382|http-nio-8080-exec-2|o.a.c.c.C.[.[.[/]|Initializing Spring FrameworkServlet 'dispatcherServlet'
2019-12-03T21:07:54.452+07:00|2|DEBUG|example-service|,,|50382|http-nio-8080-exec-2|c.c.e.MessageController|In controller sending message
2019-12-03T21:07:54.552+07:00|2|DEBUG|example-service|,,|50382|Camel (camel-1) thread #4 - RabbitMQConsumer|c.c.e.b.MessageActivity|Hello in message activity
2019-12-03T21:07:54.580+07:00|2|DEBUG|example-service|,,|50382|Camel (camel-1) thread #6 - RabbitMQConsumer|c.c.e.b.SmsActivity|Hello in sms activity

ElasticsearchIntegrationTest cannot be resolved to a type

I'm trying to write an integration test, but I get "ElasticsearchIntegrationTest cannot be resolved to a type":
public class MyTest extends ElasticsearchIntegrationTest {
#Test
public void test() {
...
}
}
the dependency looks like this:
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-test-framework</artifactId>
<version>${lucene.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>${elasticsearch.version}</version>
<scope>test</scope>
<type>test-jar</type>
</dependency>

spring boot application configuration for JaxRs based Swagger

Is there an example available to configure spring boot+Jersey+JaxRs application for Swagger?
Referring to this post, I have below code in my app and am not able to bring up the swagger UI and neither able to list the resources using
http://localhost:8080/api/root/{funcId}/entities
.
ApplicationInitializer class: (Groovy)
#Configuration
#EnableAutoConfiguration
class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run( Application.class, args)
}
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources( Application, "classpath:/META-INF/com/company/automation/functionality/bootstrap.xml");
}
#Bean
ServletRegistrationBean jerseyServlet() {
ServletRegistrationBean registration = new ServletRegistrationBean(new SpringServlet());
Map params = ["com.sun.jersey.config.property.packages":"com.company.automation.functionality.impl;com.wordnik.swagger.jersey.listing"]
registration.setInitParameters(params)
return registration;
}
#Bean
ServletRegistrationBean jerseyJaxrsConfig() {
ServletRegistrationBean registration = new ServletRegistrationBean(new JerseyJaxrsConfig());
Map params = ["swagger.api.basepath":"http://localhost:8080/api", "api.version":"1.0"]
registration.setInitParameters(params)
return registration;
}
}
Resource:
#Component
#Path('root/{funcId}/entities')
#Api (value = "root/{funcId}/entities", description = "Operations about entity Details")
#CompileStatic
class EntityDetailsResource {
..
}
[EDIT]. I am using Jersey 1.16 and can not use Jersey 2 due to application impact
I was able to get it working, but I'm not sure how good the Spring support is in Jersey 1.x, so I did it with 2.7 (that link you posted is for JAX-RS 1.x). This worked:
#Configuration
#ComponentScan
#EnableAutoConfiguration
#Path("/")
#Api(value = "home", description = "Demo API")
public class Application extends ResourceConfig implements CommandLineRunner {
#GET
#ApiOperation(value = "Get Greeting", notes = "Returns greeting")
public String home() {
return "Hello";
}
#Override
public void run(String... args) throws Exception {
SwaggerConfig config = ConfigFactory.config();
config.setBasePath("http://localhost:8080/");
config.setApiVersion("1.0.0");
ScannerFactory.setScanner(new DefaultJaxrsScanner());
ClassReaders.setReader(new JerseyApiReader());
}
public Application() {
register(Application.class);
packages("com.wordnik.swagger.jersey.listing");
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
It uses spring-boot-jersey, which is experimental, to create the Jersey servlet, but you can do that easily with a ServletRegistration #Bean if you want to stick to vanilla Boot.
I had to pin the Jersey versions and add some exclusions. Here are my dedendencies:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>com.wordnik</groupId>
<artifactId>swagger-jersey2-jaxrs_2.10</artifactId>
<version>1.3.2</version>
<exclusions>
<exclusion>
<artifactId>jsr311-api</artifactId>
<groupId>javax.ws.rs</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-jersey</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
</dependencies>
Here's an example Spring Boot app that uses Jersey 2: http://raibledesigns.com/rd/entry/a_webapp_makeover_with_spring

force glassfish 4 to use jackson 2.3

I wrote an maven application which should run on Glassfish 4.
The Standard ApplicationConfig looks like this:
#javax.ws.rs.ApplicationPath("resources")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<Class<?>>();
// following code can be used to customize Jersey 2.0 JSON provider:
try {
Class jsonProvider = Class.forName("org.glassfish.jersey.jackson.JacksonFeature");
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(getClass().getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
addRestResourceClasses(resources);
return resources;
}
The problem now is, that my resources which generate Json should use jackson 2.3 annotations.
But my glassfish uses some codehaus. ... packages to provide json. codehaus is the old version of jackson. I want to use the new one from fasterxml which provides the #JsonIdentityInfo annotation.
I thought that i could solve my problem by writing:
#javax.ws.rs.ApplicationPath("resources")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<Class<?>>();
resources.add(JacksonFeatures.class); //from the com.fasterxml.jackson.jaxrs.annotation Package
resources.add(JacksonJaxbJsonProvider.class);
resources.add(JacksonJsonProvider.class);
addRestResourceClasses(resources);
return resources;
}
But no effect. Now Glassfish uses the standard JsonProvider Moxy... which i dont want to use. Do you have any tips how i can force glassfish to use my library instead of the buildin-libraries? Or can i change the buildin library to the newer one?
And if you know how to solve this. could you please provide a little code-snippet?
EDIT 1:
After trying the first approach to solve it:
new ApplicationConfig:
#javax.ws.rs.ApplicationPath("resources")
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
//register( new GZipEncoder() );
register( JacksonFeature.class );
}
private void addMyResources() {
//a lot of resources.
}
}
JacksonFeature:
public class JacksonFeature implements Feature {
public boolean configure( final FeatureContext context ) {
String postfix = '.' + context.getConfiguration().getRuntimeType().name().toLowerCase();
context.property( CommonProperties.MOXY_JSON_FEATURE_DISABLE + postfix, true );
context.register( JsonParseExceptionMapper.class );
context.register( JsonMappingExceptionMapper.class );
context.register( JacksonJsonProvider.class, MessageBodyReader.class, MessageBodyWriter.class );
return true;
}
}
pom:
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-base</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
<version>2.4</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.4</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.3</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.3</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>7.0</version>
</dependency>
</dependencies>
Dependencies:
http://i.stack.imgur.com/uA4V2.png
Error:
SEVERE: Exception while loading the app : CDI deployment failure:WELD-001408 Unsatisfied dependencies for type [Ref<ContainerRequest>] with qualifiers [#Default] at injection point [[BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] #Inject org.glassfish.jersey.server.internal.routing.UriRoutingContext(Ref<ContainerRequest>, ProcessingProviders)]
org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Ref<ContainerRequest>] with qualifiers [#Default] at injection point [[BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] #Inject org.glassfish.jersey.server.internal.routing.UriRoutingContext(Ref<ContainerRequest>, ProcessingProviders)]
at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:403)
at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:325)
at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:177)
...
or
SEVERE: Exception while loading the app
SEVERE: Undeployment failed for context /blueserver
INFO: file:/C:/bluetrail/blueserver/target/blueserver-0.0.0.1/WEB-INF/classes/_de.bluetrail_blueserver_war_0.0.0.1PU logout successful
SEVERE: Exception while loading the app : CDI deployment failure:WELD-001408 Unsatisfied dependencies for type [IterableProvider<InjectionResolver<Object>>] with qualifiers [#Default] at injection point [[BackedAnnotatedParameter] Parameter 2 of [BackedAnnotatedConstructor] #Inject org.glassfish.jersey.internal.inject.JerseyClassAnalyzer(#Named ClassAnalyzer, IterableProvider<InjectionResolver<Object>>)]
EDIT 2:
i will now post some classes of my project. In that classes i included all Annotations that i use.
i have like 16 entities like that:
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToOne;
#Entity
#JsonIdentityInfo(generator = ObjectIdGenerators.None.class, property = "id", scope=Address.class)
//the JsonIdentityInfo is the reason i need Jackson 2
public class Address implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String postalCode;
private String city;
private String country;
private String street;
private String houseNumber;
#Embedded
private Coordinate coordinate;
//getters, setters , etc.
}
then i have a lot of DAO's like that:
import de.ibs.trail.entity.Address;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
#Stateless
public class AddressDao extends GenericDao {
public Address getAddress(long id){
return em.find(Address.class, id);
}
public List<Address> getAddresses(){
List<Address> address = em.createQuery("SELECT a FROM Address a", Address.class).getResultList();
return address;
}
}
and finally i have a lot of REssources like that:
import de.bluetrail.blueserver.dao.AddressDao;
import de.ibs.trail.entity.Address;
import java.util.List;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
#Path("dummy")
#Stateless
public class DummyResource {
#Context
private UriInfo context;
#Inject userAuth user;
#Inject addressDao AddressDao;
public DummyResource() {
}
#GET
#Produces("application/json")
public List<Address> getAddress() {
return AddressDao.getAddresses();
}
}
Thats the first part. As a second part i have a class for some Google Services. Because i want to try to use some Google GeoLocation and Routing. I put the Google-Code into a pasteBin file, because its so huge:
http://pastebin.com/u3e0dms6
there i use libraries like:
import com.fasterxml.jackson.databind.ObjectMapper;
import de.ibs.trail.entity.Address;
//some other entities
//...
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Set;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
I hope that helps. All the other classes use the same annotations.
First make sure you have the following in your pom.xml:
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>${jackson.version}</version>
</dependency>
Then make sure you DO NOT have this in any pom.xml:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.5</version>
</dependency>
Then you need to disable moxy. The easiest way to do this is to ditch your Application class and replace is with a ResourceConfig class. First lets create YOUR JacksonFeature class:
public class JacksonFeature implements Feature {
public boolean configure( final FeatureContext context ) {
String postfix = '.' + context.getConfiguration().getRuntimeType().name().toLowerCase();
context.property( CommonProperties.MOXY_JSON_FEATURE_DISABLE + postfix, true );
context.register( JsonParseExceptionMapper.class );
context.register( JsonMappingExceptionMapper.class );
context.register( JacksonJsonProvider.class, MessageBodyReader.class, MessageBodyWriter.class );
return true;
}
}
Two interesting things here, first I disabled moxy and second I made sure to add the JacksonException mappers. This way you will get better errors than internal server error if there is a parsing or generation exception. Okay, last step it so rewrite your Application as a ResourceConfig class:
#javax.ws.rs.ApplicationPath("resources")
public class RestApplication extends ResourceConfig {
public RestApplication() {
register( new GZipEncoder() );
register( JacksonFeature.class );
}
private void addMyResources() {
register( MyResource1.class );
register( MyResource2.class );
}
}
That should do it. Also, instead of registering the resources one by one like this, if you know their path you can just remove all that code and add this to the constructor of RestApplication:
package( "com.me.myrestresourcespackage" );
Hope this helps.

How to make m2eclipse (Maven) point to the "persistence.xml" path?

I working with Eclipse Helios, m2eclipse Maven plugin and Glassfish plugin.
I edited the "pom.xml" file so that I can get the DerbyClient and the JPA Persistence classes.
<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>com.apress.javaee6</groupId>
<artifactId>chapter02</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>chapter02</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
<version>10.6.1.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4.3</version>
<type>maven-plugin</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>EclipseLink Repo</id>
<url>http://www.eclipse.org/downloads/download.php?r=1&nf=1&file=/rt/eclipselink/maven.repo</url>
</repository>
</repositories>
</project>
Then, I created the "src/main/resrouce" directory and put a "persistence.xml" file that contains:
<xml version="1.0" encoding="UTF-8">
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="chapter02PU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.apress.javaee6.chapter02.Book</class>
<properties>
<property name="eclipselink.target-datababase" value="DERBY"/>
<property name="eclipselink.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
<property name="eclipselink.jdbc.url" value="jdbc:derby://localhost:1527/chapter02DB;create=true"/>
<property name="eclipselink.jdbc.user" value="APP"/>
<property name="eclipselink.jdbc.password" value="APP"/>
<property name="eclipselink.jdbc.ddl-generation" value="create-tables"/>
<property name="eclipselink.jdbc.logging-level" value="INFO"/>
</properties>
</persistence-unit>
</persistence>
</xml>
Of course, the derby server runs perfectly.
And I have create the following Book Class:
package com.apress.javaee6.chapter02;
import javax.persistence.*;
#Entity
#NamedQuery(name="findAllBooks", query="SELECT b from Book b")
public class Book {
#Id #GeneratedValue
private Long id;
#Column(nullable = false)
private String title;
private float price;
#Column(length = 1000)
private String description;
private String isbn;
private Integer nbOfPage;
private Boolean illustrations;
public Book() {
super();
}
public Book(Long id, String title, float price, String description,
String isbn, Integer nbOfPage, Boolean illustrations) {
super();
this.id = id;
this.title = title;
this.price = price;
this.description = description;
this.isbn = isbn;
this.nbOfPage = nbOfPage;
this.illustrations = illustrations;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public Integer getNbOfPage() {
return nbOfPage;
}
public void setNbOfPage(Integer nbOfPage) {
this.nbOfPage = nbOfPage;
}
public Boolean getIllustrations() {
return illustrations;
}
public void setIllustrations(Boolean illustrations) {
this.illustrations = illustrations;
}
}
The main function is here:
package com.apress.javaee6.chapter02;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class Main {
/**
* #param args
*/
public static void main(String[] args) {
// Create an instance of book
Book book = new Book();
book.setTitle("The Hitchhiker's guide to the Galaxy");
book.setPrice(12.5F);
book.setDescription("Science fiction comedy book");
book.setIsbn("1-84023-742-2");
book.setIllustrations(false);
// Gets an entity manager and a transaction
EntityManagerFactory emf = Persistence.createEntityManagerFactory("chapter02PU");
EntityManager em = emf.createEntityManager();
// Persists the book to the database
EntityTransaction tx = em.getTransaction();
try {
tx.begin();
em.persist(book);
tx.commit();
em.close();
emf.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The problem is that the "persistence.xml" is not recognized.
How can I make Maven point to the "persistence.xml" file?
When I active the Maven console and "Update Dependencies", I got the following (bad) info:
28/06/10 15:20:36 CEST: [INFO] Using 'UTF-8' encoding to copy filtered resources.
28/06/10 15:20:36 CEST: [INFO] skip non existing resourceDirectory /home/zakaria/workspace/chapter02/src/main/resources
28/06/10 15:20:36 CEST: [INFO] Using 'UTF-8' encoding to copy filtered resources.
28/06/10 15:20:36 CEST: [INFO] skip non existing resourceDirectory /home/zakaria/workspace/chapter02/src/test/resources
So i think he tried somewhere to create the "resources" directories and cannot get them after the build.
Thank you so much ;)
Regards
You don't tell maven to "point" on a file, you put files in a directory that end up on the class path. For resources, you're supposed to use src/main/resources.
In other words, just put the persistence.xml in src/main/resources/META-INF.
I'm using m2eclipse 0.10.0 and I don't use any special workaround, it just works for at least 3 projects in my workspace of type jar, ejb and war.
If you're using m2eclipse 0.10.0, not having the resources recognized is a known problem (see m2eclipse user list). There is a workaround described here:
https://docs.sonatype.org/pages/viewpage.action?pageId=2949459
Using maven-resources-plugin version 2.4.2 or 2.4.3 may also work better than 2.4.
According to JPA standard persistence.xml should reside in the root of META-INF folder. So putting in into src/main/resources/META-INF should work