I've googled and tried but I cant get Providers to work in my project.
POM.XML:
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.22.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.22.1</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-servlet-api</artifactId>
<version>9.0.0.M1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.22.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>1.19</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
My Filter:
package xxxxxxx
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.DatatypeConverter;
#Provider
public class BasicAuthFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext)
throws IOException {
String authorization = requestContext.getHeaderString("Authorization");
if (!auth(authorization)) {
requestContext.abortWith(Response
.status(Response.Status.UNAUTHORIZED)
.entity("User cannot access the resource.")
.build());
}
}
private Boolean auth(String authorization)
throws UnsupportedEncodingException {
if (authorization != null && authorization.startsWith("Basic")) {
String base64Credentials = authorization
.substring("Basic".length()).trim();
byte[] decoded = DatatypeConverter
.parseBase64Binary(base64Credentials);
final String[] values = new String(decoded, "UTF-8").split(":", 2);
if (values.length == 2 && values[0].equals("usuario")
&& values[1].equals("senha")) {
return true;
}
}
return false;
}
}
My ResourceConfig class:
import javax.ws.rs.ApplicationPath;
import org.glassfish.jersey.server.ResourceConfig;
import xxx.providers.BasicAuthFilter;
import xxx.resource.LogParserResource;
#ApplicationPath("rest")
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
register(BasicAuthFilter.class);
register(MyResource.class);
}
}
Filter is not triggered. Anything wrong in my configuration?
WEB.XML is empty and the Resource is working fine. Any suggestions??
Thanks.
i noticed, that this dependency is not the version of the other ones:
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>1.19</version>
</dependency>
you could try to use:
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.22.1</version>
</dependency>
and then notice the documentation:
Important
Servlet 2.x API does not provide a way how to programmatically read
the filter mappings. To make application deployed using filter work
correctly, either Servlet 3.x container must be used
(jersey-container-servlet instead of jersey-container-servlet-core),
or the context path of the app needs to be defined using init
parameter jersey.config.servlet.filter.contextPath.
see: https://jersey.java.net/documentation/latest/deployment.html#deployment.servlet
Related
There is an application that is configured by hk2 dependency injection.
the pom.xml :
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<java.version>17</java.version>
<junit.version>5.4.0</junit.version>
<jsonassert.version>1.5.0</jsonassert.version>
<jersey.version>3.0.2</jersey.version>
</properties>
<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>
<!-- Grizzly 2 HTTP Server -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
</dependency>
<!-- Jersey DI and core-->
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.hk2</groupId>
<artifactId>hk2-metadata-generator</artifactId>
<version>3.0.2</version>
</dependency>
<!-- add jackson as json provider -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
</dependency>
<!-- Need this to hide warning for jakarta.activation.DataSource -->
<dependency>
<groupId>jakarta.activation</groupId>
<artifactId>jakarta.activation-api</artifactId>
<version>2.0.1</version>
</dependency>
<!-- JUnit 5 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- test json data -->
<dependency>
<groupId>org.skyscreamer</groupId>
<artifactId>jsonassert</artifactId>
<version>${jsonassert.version}</version>
<scope>test</scope>
</dependency>
and MyResource.java:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.mkyong.json.service.MessageService;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
#Path("/hello")
public class MyResource {
private static final ObjectMapper mapper = new ObjectMapper();
#Inject
#Named("aws")
private MessageService awsService;
#Inject
#Named("azure")
private MessageService azureService;
#Path("/hk2/aws")
#GET
#Produces(MediaType.TEXT_PLAIN)
public String helloAws() {
String result = awsService.getHello();
ObjectNode json = mapper.createObjectNode();
return result;
}
#Path("/hk2/azure")
#GET
#Produces(MediaType.TEXT_PLAIN)
public String helloAzure() {
return azureService.getHello();
}
}
and AutoScanFeature.java :
import jakarta.inject.Inject;
import jakarta.ws.rs.core.Feature;
import jakarta.ws.rs.core.FeatureContext;
import org.glassfish.hk2.api.DynamicConfigurationService;
import org.glassfish.hk2.api.MultiException;
import org.glassfish.hk2.api.Populator;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.utilities.ClasspathDescriptorFileFinder;
import org.glassfish.hk2.utilities.DuplicatePostProcessor;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
public class AutoScanFeature implements Feature {
#Inject
ServiceLocator serviceLocator;
#Override
public boolean configure(FeatureContext context) {
DynamicConfigurationService dcs =
serviceLocator.getService(DynamicConfigurationService.class);
Populator populator = dcs.getPopulator();
try {
// Populator - populate HK2 service locators from inhabitants files
// ClasspathDescriptorFileFinder - find files from META-INF/hk2-locator/default
populator.populate(
new ClasspathDescriptorFileFinder(this.getClass().getClassLoader()),
new DuplicatePostProcessor());
} catch (IOException | MultiException ex) {
Logger.getLogger(AutoScanFeature.class.getName()).log(Level.SEVERE, null, ex);
}
return true;
}
}
Service interface:
#Contract
public interface UserService {
void add(User user);
}
and its implementation:
#Service
public class UserServiceImpl implements UserService {
#Override
public void add(User user) {
super.save(user, hibernateOracleTestXML);
}
}
Everything is working correctly and dependency injection is only worked by only #Service and #Contract, but I want to use #Singleton or something else for such as DAO layer.
Another hand It does not work when I use #Singleton or something else except #Service
How to solve this problem?
The #Contract and #Service are both for its default injection, according to the question, these annotations are not suitable for DAO layer, so I solved this issue by org.glassfish.hk2.utilities.binding.AbstractBinder like this:
#Override
protected void configure() {
Reflections reflections = new Reflections(packageName);
Set<Class<?>> repositories = reflections.getTypesAnnotatedWith(Repository.class, true);
repositories.stream().forEach(repo -> {
BeanAddress beanAddresses = repo.getAnnotationsByType(BeanAddress.class)[0];
try {
Class<?> requiredClass = Class.forName(beanAddresses.implPackageName());
bind(requiredClass).to(repo)
.named(Class.class.getCanonicalName()).in(Singleton.class);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
});
...
As it shows, I manually bind the interface to its class of DAO layers by an annotation that is made by myself(BeanAddress.class)
I'm new to Spring and I'm getting the error below when I try to run my application. Am I missing any Spring annotation?
Should I create a JpaUpdateRepositoryImpl class instead?
APPLICATION FAILED TO START
Description:
Parameter 1 of constructor in com.myapp.domain.service.StoreAsyncService required a bean of type 'com.myapp.domain.repository.JpaUpdateRepository' that could not be found.
Action:
Consider defining a bean of type 'com.myapp.domain.repository.JpaUpdateRepository' in your configuration.
Service Class
package com.myapp.domain.service;
import com.myapp.domain.model.Store;
import com.myapp.domain.repository.JpaUpdateRepository;
import com.myapp.facade.ElasticSearchFacade;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ForkJoinPool;
#Async
#Service
public class StoreAsyncService {
static Logger logger = LoggerFactory.getLogger(StoreAsyncService.class);
private Integer partitionSize = 1000;
private Integer parallelism = 4;
private final ElasticSearchFacade elasticSearch;
private final JpaUpdateRepository repository;
public StoreAsyncService(ElasticSearchFacade elasticSearch, JpaUpdateRepository repository) {
this.elasticSearch = elasticSearch;
this.repository = repository;
}
public void exportStores(List<Store> stores) {
List<List<Store>> storesSubset = Lists.partition(stores, partitionSize);
ForkJoinPool pool = new ForkJoinPool(parallelism);
for (List<Store> storesItem : storesSubset) {
CompletableFuture.runAsync(() -> sendToElastic(storesItem), pool);
}
pool.shutdown();
LocalDateTime localDateTime = LocalDateTime.now();
repository.updateCadConfiguracaoWithLastExecutionDate(localDateTime.format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss")));
}
public void sendToElastic(List<Store> stores) {
elasticSearch.post(stores);
logger.info("sentToElastic - {} Stores sent to Elastic", stores.size());
}
}
Repository
package bcom.myapp.domain.repository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
#Repository
public interface JpaUpdateRepository extends CrudRepository<Object, Integer> {
#Modifying
#Query("UPDATE CONFIG c SET c.VALOR = :lastExecutionDate WHERE c.CODE = 'EXPORTACAO_WORKER_STORE' ")
void updateCadConfiguracaoWithLastExecutionDate(#Param("lastExecutionDate") String lastExecutionDate);
}
POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
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.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>br.com.getnet</groupId>
<artifactId>cstores-worker</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>tores-worker</name>
<properties>
<java.version>11</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.3.1.RELEASE</version><!--$NO-MVN-MAN-VER$-->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.7.RELEASE</version><!--$NO-MVN-MAN-VER$-->
</dependency>
<dependency>
<groupId>com.oracle.ojdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>19.3.0.0</version><!--$NO-MVN-MAN-VER$-->
<exclusions>
<exclusion>
<groupId>com.oracle.ojdbc</groupId>
<artifactId>simplefan</artifactId>
</exclusion>
<exclusion>
<groupId>com.oracle.ojdbc</groupId>
<artifactId>ons</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.4.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version><!--$NO-MVN-MAN-VER$-->
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.google.collections</groupId>
<artifactId>google-collections</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.10.1</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.10.1</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>4.1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Configuration
package com.myapp.infrastructure.config;
import org.apache.http.HttpHost;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
import static org.apache.http.auth.AuthScope.ANY;
#Configuration
#EnableElasticsearchRepositories(basePackages = "com.myapp.infrastructure")
#ComponentScan(basePackages = {"com.myapp.domain"})
public class ElasticSearchConfig {
#Value("${app.url}")
String elasticPostUrl;
#Value("${app.port}")
Integer elasticPostPort;
#Value("${app.username}")
String userName;
#Value("${app.password}")
String userPassword;
BasicCredentialsProvider credentialsProvider;
#Bean
public RestHighLevelClient client() {
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(userName, userPassword);
this.credentialsProvider = new BasicCredentialsProvider();
this.credentialsProvider.setCredentials(ANY, credentials);
HttpHost httpHost = new HttpHost(elasticPostUrl, elasticPostPort, "http");
RestClientBuilder builder = RestClient.builder(httpHost)
.setHttpClientConfigCallback(httpClientBuilder ->
httpClientBuilder.setDefaultCredentialsProvider(
this.credentialsProvider));
return new RestHighLevelClient(builder);
}
#Bean
public ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchRestTemplate(client());
}
}
You need to use #EnableAsync on the class level instead of #Async and use #Async on the Methods that shall run asynchronously, As the #EnableAsync annotation applied on application classes for asynchronous behavior and look for methods marked with #Async annotation and run in background thread pools.
It would be nice to check your imports, package declaration and config java files. Please add them and I will be happy to help.
You can try to set up a scan for your repository in your SpringBoot Main application like:
#EnableJpaRepositories("...your.repository.package.name")
EDIT: Being more specific now i noticed a conflict i want to use BOTH dependencies below:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-binding</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.3.1</version>
</dependency>
Basically, I am trying to ignore a property (#JsonIgnore), but none of my Jackson annotations are working. Even the #JsonProperty. I tried to add the #JsonIgnore in getters and setters methods, but same behavior.
I also tried to follow official documentation, and tried different libraries
import org.codehaus.jackson.annotate.JsonIgnore; (Same Behavior)
import com.fasterxml.jackson.annotation.JsonIgnore; (Same Behavior)
I see similar posts like #12595351
My Response from the Controller, should not display the Revoked. Attribute, but i got this response:
Actual Response
{
"accessToken": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJqb2huLmRvZUBleGFtcGxlLmNvbSIsImlzcyI6ImpvaG4uZG9lQGV4YW1wbGUuY29tIiwiaWF0IjoxNTI1MzI1Nzk1LCJleHAiOjE1MjUzMzI5OTV9.uri3pRwXQHHG09F-wM40qfuRMRVu_WBK3HlfquGvwYc",
"expiresAt": "2018-05-03T07:36:35.087Z[UTC]",
"expiresIn": 7199,
"issuedAt": "2018-05-03T05:36:35.087Z[UTC]",
"refreshToken": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJqb2huLmRvZUBleGFtcGxlLmNvbSIsImlzcyI6ImpvaG4uZG9lQGV4YW1wbGUuY29tIiwiaWF0IjoxNTI1MzI1Nzk1LCJleHAiOjE1MjU5MzA1OTV9.xj2oytAVwiAIR8U2upJkPH_BdORuJUNbiicvuvGFz0w",
"revoked": false,
"type": "Bearer"
}
Expected Response
{
"accessToken": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJqb2huLmRvZUBleGFtcGxlLmNvbSIsImlzcyI6ImpvaG4uZG9lQGV4YW1wbGUuY29tIiwiaWF0IjoxNTI1MzI1Nzk1LCJleHAiOjE1MjUzMzI5OTV9.uri3pRwXQHHG09F-wM40qfuRMRVu_WBK3HlfquGvwYc",
"expiresAt": "2018-05-03T07:36:35.087Z[UTC]",
"expiresIn": 7199,
"issuedAt": "2018-05-03T05:36:35.087Z[UTC]",
"refreshToken": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJqb2huLmRvZUBleGFtcGxlLmNvbSIsImlzcyI6ImpvaG4uZG9lQGV4YW1wbGUuY29tIiwiaWF0IjoxNTI1MzI1Nzk1LCJleHAiOjE1MjU5MzA1OTV9.xj2oytAVwiAIR8U2upJkPH_BdORuJUNbiicvuvGFz0w",
"type": "Bearer"
}
pom.xml (Using Maven)
<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>com.wedhany.fimper</groupId>
<artifactId>fimper</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>fimper</name>
<build>
<finalName>fimper</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<inherited>true</inherited>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<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>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>de.mkammerer</groupId>
<artifactId>argon2-jvm</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-dbcp</artifactId>
<version>9.0.1</version>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>5.0.7</version>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-binding</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring4</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-jdk-http</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.17.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.9.Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springframework.version}</version>
</dependency>
</dependencies>
<profiles>
<profile>
<id>Development</id>
<dependencies>
<dependency>
<groupId>com.github.blocoio</groupId>
<artifactId>faker</artifactId>
<version>1.2.7</version>
</dependency>
</dependencies>
</profile>
</profiles>
<properties>
<jersey.version>2.27</jersey.version>
<springframework.version>4.3.16.RELEASE</springframework.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
Token.java (My Model)
package com.wedhany.models;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.wedhany.models.enums.token.GrantType;
import com.wedhany.models.enums.token.Type;
import java.util.Date;
public class Token {
/**
* Attributes
*/
private String accessToken;
private String refreshToken;
#JsonIgnore
private boolean revoked;
#JsonProperty("expires_at")
private Date expiresAt;
private Date issuedAt;
private GrantType grantType;
private Type type;
private User user;
/**
* #return Token TTL in seconds.
*/
public long getExpiresIn() {
return this.expiresAt.getTime() < new Date().getTime()
? 0
: (this.expiresAt.getTime() - new Date().getTime()) / 1000;
}
/**
* #return Token that will grant authentication and authorization.
*/
public String getAccessToken() {
return accessToken;
}
/**
* #param accessToken Token string.
*/
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
/**
* #return Token used to request a new token.
*/
public String getRefreshToken() {
return refreshToken;
}
/**
* #return Invalid token if true.
*/
public boolean isRevoked() {
return revoked;
}
/**
* #param revoked True for invalid.
*/
public void setRevoked(boolean revoked) {
this.revoked = revoked;
}
/**
* #param refreshToken Refresh token.
*/
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
/**
* #return Token's expiration date.
*/
public Date getExpiresAt() {
return expiresAt;
}
/**
* #param expiresAt Token's expiration date.
*/
public void setExpiresAt(Date expiresAt) {
this.expiresAt = expiresAt;
}
/**
* #return Date where the token was requested.
*/
public Date getIssuedAt() {
return issuedAt;
}
/**
* #param issuedAt Date where the token was requested.
*/
public void setIssuedAt(Date issuedAt) {
this.issuedAt = issuedAt;
}
/**
* #return Type of the token.
*/
public Type getType() {
return type;
}
/**
* #param type Type of the token.
*/
public void setType(Type type) {
this.type = type;
}
/**
* #return How the token was claimed.
*/
public GrantType getGrantType() {
return grantType;
}
/**
* #param grantType Set token type of grant.
*/
public void setGrantType(GrantType grantType) {
this.grantType = grantType;
}
/**
* #return Owner of the token
*/
public User getUser() {
return user;
}
/**
* #param user Token's owner.
*/
public void setUser(User user) {
this.user = user;
}
}
AuthenticationController
package com.wedhany.controllers;
import com.wedhany.exceptions.AuthorizationException;
import com.wedhany.models.Token;
import com.wedhany.models.User;
import com.wedhany.services.AuthenticationService;
import org.springframework.beans.factory.annotation.Autowired;
import javax.security.sasl.AuthenticationException;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
#Path("auth")
public class AuthenticationController {
#Autowired
private AuthenticationService authenticationService;
#POST
#Path("login")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response login(User user, #HeaderParam("user-agent") String userAgent) throws Exception {
try {
// Authenticate the user using the credentials provided
this.authenticationService.authenticate(user.getEmail(), user.getPassword());
// Issue a token for the user
Token token = this.authenticationService.issueToken(user.getEmail(), userAgent);
// Return the token on the response
return Response.ok(token).build();
} catch (AuthorizationException e) {
return Response.status(Response.Status.UNAUTHORIZED).build();
} catch (AuthenticationException e) {
return Response.status(Response.Status.FORBIDDEN).build();
}
}
#POST
#Path("refresh")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response refresh(Token token, #HeaderParam("user-agent") String userAgent) throws AuthenticationException {
return Response.status(Response.Status.CREATED)
.entity(this.authenticationService.refresh(token.getRefreshToken(), userAgent))
.build();
}
#POST
#Path("register")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response register(User user) {
user = authenticationService.save(user);
return Response.status(Response.Status.CREATED)
.entity(user)
.build();
}
}
Choose either one of the following but not both:
<!-- JSON-B (JSR-347) support -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-binding</artifactId>
<version>2.27</version>
</dependency>
<!-- Jackson 2.x support -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.27</version>
</dependency>
Both Jackson and JSON-B provide JSON from/to Java binding:
Jackson is a quite mature library for JSON processing. It's flexible and has a fair number of extensions modules.
JSON-B is also referenced as JSR-347. It's an specification for JSON binding. The actual implementation will be provided by Eclipse Yasson, which is the reference implementation of the JSR-347.
If you want go for jersey-media-json-jackson, you are supposed to use Jackson annotations. To ignore a property, for instance, use #JsonIgnore.
If you want to go for jersey-media-json-binding, you are supposed to use JSON-B annotations. To ignore a property, for instance, use #JsonbTransient.
You are using jersey-bom, a dependency management artifact that consolidate and centralize the management of dependency versions (without actually adding the dependencies to the project).
So you don't need to specify the version of the org.glassfish.jersey artifacts. Use one of the following (without version):
<!-- JSON-B (JSR-347) support -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-binding</artifactId>
</dependency>
<!-- Jackson 2.x support -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
</dependency>
See more details here and here.
The following code works for me with jackson version 2.8.10
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JsonIgnoreExample {
private static class BeanWithIgnore {
#JsonIgnore
public int id;
public String name;
public BeanWithIgnore(int id, String name) {
this.id = id;
this.name = name;
}
}
public static void main(String[] args) throws JsonProcessingException {
BeanWithIgnore bean = new BeanWithIgnore(1, "My bean");
String result = new ObjectMapper().writeValueAsString(bean);
System.out.println(result); // {"name":"My bean"}
}
}
Basically the jersey-media-json-binding and jersey-media-json-jackson have similar behavior. You can't use both at the same time. The reason the jersey-media-json-jackson was not working it is because the provider which have more priority is the jersey-media-json-binding.
I don't know the whole configuration of your project so one think you can do that is, create manually JSON and then send to response like:
ObjectMapper maper = new ObjectMapper();
return Response.ok(maper.writer().withDefaultPrettyPrinter().writeValueAsString(tokenObject));
It will work like manual conversion without using auto serialization by Jersey.
Note: This thing is not recommendable but it should work.
You need this dependency for conversion:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.2.3</version>
</dependency>
This works for me, I have these libs in my pom.xml:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${org.glassfish.jersey.core.version}</version>
<scope>provided</scope>
</dependency>
<!-- ************** Jackson XML and JSON API ************************* -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>${org.glassfish.jersey.core.version}</version>
<scope>provided</scope>
</dependency>
Just remove that property from your class and add this annotation:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
#JsonIgnoreProperties(ignoreUnknown=true)
public class Token {
// ... keep only the properties you want to map
this will tell Jackson to only bind the properties which you actually have in your class ignoring all the rest that might be present in the JSON output.
I want to register a class component(Object) in jersey not class reference.
I create a XYZResource class that be called by main() method and it be configured through jersey with DBI object. DAOService daoService has connection DBI connection and the getDetails() that execute query and return result.
I use IntelliJ IDE and run through Main Class com.example.Main
when i hit my url http://localhost:9000/resource/test than it through error
javax.servlet.ServletException: A MultiException has 1 exceptions. They are:
1. java.lang.NoSuchMethodException: Could not find a suitable constructor in com.example.AdminResource class.
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:392)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:382)
org.glassfish.jersey.servlet.ServletContainer.doFilter(ServletContainer.java:535)
org.glassfish.jersey.servlet.ServletContainer.doFilter(ServletContainer.java:483)
org.glassfish.jersey.servlet.ServletContainer.doFilter(ServletContainer.java:420)
root cause
A MultiException has 1 exceptions. They are:
1. java.lang.NoSuchMethodException: Could not find a suitable constructor in com.example.AdminResource class.
org.jvnet.hk2.internal.Collector.throwIfErrors(Collector.java:88)
org.jvnet.hk2.internal.Utilities.justCreate(Utilities.java:852)
org.jvnet.hk2.internal.ServiceLocatorImpl.create(ServiceLocatorImpl.java:814)
org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:906)
org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:898)
org.glassfish.jersey.internal.inject.Injections.getOrCreate(Injections.java:174)
org.glassfish.jersey.server.model.MethodHandler$ClassBasedMethodHandler.getInstance(MethodHandler.java:185)
org.glassfish.jersey.server.internal.routing.PushMethodHandlerRouter.apply(PushMethodHandlerRouter.java:103)
org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:128)
org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:131)
org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:131)
org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:131)
org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:131)
org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:110)
org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:65)
org.glassfish.jersey.process.internal.Stages.process(Stages.java:197)
org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:250)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
org.glassfish.jersey.internal.Errors.process(Errors.java:315)
org.glassfish.jersey.internal.Errors.process(Errors.java:297)
org.glassfish.jersey.internal.Errors.process(Errors.java:267)
org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:318)
org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:236)
org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1010)
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:373)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:382)
org.glassfish.jersey.servlet.ServletContainer.doFilter(ServletContainer.java:535)
org.glassfish.jersey.servlet.ServletContainer.doFilter(ServletContainer.java:483)
org.glassfish.jersey.servlet.ServletContainer.doFilter(ServletContainer.java:420)
root cause
java.lang.NoSuchMethodException: Could not find a suitable constructor in com.example.AdminResource class.
org.glassfish.jersey.internal.inject.JerseyClassAnalyzer.getConstructor(JerseyClassAnalyzer.java:189)
org.jvnet.hk2.internal.Utilities.getConstructor(Utilities.java:159)
org.jvnet.hk2.internal.Utilities.justCreate(Utilities.java:850)
org.jvnet.hk2.internal.ServiceLocatorImpl.create(ServiceLocatorImpl.java:814)
org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:906)
org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:898)
org.glassfish.jersey.internal.inject.Injections.getOrCreate(Injections.java:174)
org.glassfish.jersey.server.model.MethodHandler$ClassBasedMethodHandler.getInstance(MethodHandler.java:185)
org.glassfish.jersey.server.internal.routing.PushMethodHandlerRouter.apply(PushMethodHandlerRouter.java:103)
org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:128)
org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:131)
org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:131)
org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:131)
org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:131)
org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:110)
org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:65)
org.glassfish.jersey.process.internal.Stages.process(Stages.java:197)
org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:250)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
org.glassfish.jersey.internal.Errors.process(Errors.java:315)
org.glassfish.jersey.internal.Errors.process(Errors.java:297)
org.glassfish.jersey.internal.Errors.process(Errors.java:267)
org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:318)
org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:236)
org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1010)
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:373)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:382)
org.glassfish.jersey.servlet.ServletContainer.doFilter(ServletContainer.java:535)
org.glassfish.jersey.servlet.ServletContainer.doFilter(ServletContainer.java:483)
org.glassfish.jersey.servlet.ServletContainer.doFilter(ServletContainer.java:420)
Technology Use:
Java - 8
Embedded tomcat - 8
Jersey 2.5.1 (REST)
JDBI 2.63.1 (DB Service)
Main.java
package com.example;
import com.core.db.DAOService;
import com.example.servlets.HelloWorldServlet;
import com.example.util.abc;
import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.Tomcat;
import org.skife.jdbi.v2.DBI;
public class Main {
public static void main (String[] args) {
Tomcat tomcat = new Tomcat();
tomcat.setPort(9000);
String baseDoc = new File("src/main/webapp").getAbsolutePath();
Context ctx = tomcat.addContext("/servletSample", baseDoc);
tomcat.addWebapp(null, "", baseDoc);
tomcat.addServlet(ctx, "HelloWorld", new HelloWorldServlet());
ctx.addServletMapping("/*", "HelloWorld");
try {
final DBI XYZDBI = new DBI(/*url*/, /*username*/, /*password*/);
/* DAOService is a class that has function getDetails() that retrive data from database */
final DAOService daoService = XYZDBI.onDemand(DAOService.class);
final org.glassfish.jersey.server.ResourceConfig jerseyResource = new org.glassfish.jersey.server.ResourceConfig();
/* Register XYZResource class instance with jersey Resouce */
jerseyResource.register(new XYZResource(daoService));
tomcat.start();
} catch (LifecycleException e) {
e.printStackTrace();
}
while (true) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-jersey</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<build>
<finalName>my-embed-tomcat</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<inherited>true</inherited>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Dependencies for Jersey Web Application -->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-servlet-api</artifactId>
<version>7.0.42</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-mvc-jsp</artifactId>
<version>2.5.1</version>
</dependency>
<!-- Dependencies for Embedded Tomcat -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>8.0.26</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-logging-juli</artifactId>
<version>8.0.26</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>8.0.26</version>
</dependency>
<dependency>
<!--org.skife.jdbi.v2-->
<groupId>org.jdbi</groupId>
<artifactId>jdbi</artifactId>
<version>2.63.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>2.8.0.rc2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.8.0.rc2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.8.0.rc2</version>
</dependency>
<dependency>
<groupId>microsoft.com</groupId>
<artifactId>sqlJdbc4</artifactId>
<version>4.0.2206.100</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
XYZResource.java
package com.example;
import com.core.db.DAOService;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.*;
#Path("resource")
public class XYZResource {
private final DAOService daoService;
public XYZResource(DAOService daoService) {
this.daoService = daoService;
}
#GET
public String helloworld() {
return "User - Resource";
}
#GET
#Path("/test")
public Response test() {
Set<String> User = daoService.getDetails();
Iterator<String> itr = User.iterator();
return Response.status(200).entity(itr.next().toString())
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET")
.build();
}
}
}
MyApplication.java
package com.example;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.mvc.jsp.JspMvcFeature;
public class MyApplication extends ResourceConfig {
public MyApplication() {
this.packages(MyApplication.class.getPackage().getName()).register(JspMvcFeature.class);
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>Jersey Jersey Application</display-name>
<filter>
<filter-name>Jersey Application Filter</filter-name>
<filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.example.MyApplication</param-value>
</init-param>
<!-- pass to next filter if Jersey/App returns 404 -->
<init-param>
<param-name>jersey.config.servlet.filter.forwardOn404</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Jersey Application Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Update
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>jersey-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<build>
<finalName>my-embed-tomcat</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<inherited>true</inherited>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<tomcat.version>8.0.28</tomcat.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
s
<dependency>
<groupId>org.glassfish.jersey.bundles.repackaged</groupId>
<artifactId>jersey-guava</artifactId>
<version>2.25.1</version>
</dependency>
<!-- Dependencies for Jersey Web Application -->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-servlet-api</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-mvc-jsp</artifactId>
<version>2.5.1</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.5.1</version>
</dependency>
<!-- Dependencies for Embedded Tomcat -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-logging-juli</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<!--org.skife.jdbi.v2-->
<groupId>org.jdbi</groupId>
<artifactId>jdbi</artifactId>
<version>2.63.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>2.8.0.rc2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.8.0.rc2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.8.0.rc2</version>
</dependency>
<dependency>
<groupId>microsoft.com</groupId>
<artifactId>sqlJdbc4</artifactId>
<version>4.0.2206.100</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
</project>
Main.java
package com.example;
import org.apache.catalina.Context;
import org.apache.catalina.servlets.DefaultServlet;
import org.apache.catalina.startup.Tomcat;
import org.apache.tomcat.util.descriptor.web.FilterDef;
import org.apache.tomcat.util.descriptor.web.FilterMap;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.mvc.jsp.JspMvcFeature;
import org.glassfish.jersey.servlet.ServletContainer;
import org.glassfish.jersey.servlet.ServletProperties;
import javax.servlet.Filter;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import java.io.File;
/**
* #author Paul Samsotha.
*/
public class Main {
public static void main(String... args) throws Exception {
Tomcat tomcat = new Tomcat();
tomcat.setPort(9000);
File base = new File(".");
Context context = tomcat.addContext("", base.getAbsolutePath());
Tomcat.addServlet(context, "default", new DefaultServlet());
context.addServletMapping("/*", "default");
final FilterDef def = new FilterDef();
final FilterMap map = new FilterMap();
def.setFilterName("jerseyFilter");
def.setFilter(getJerseyFilter());
context.addFilterDef(def);
map.setFilterName("jerseyFilter");
map.addURLPattern("/api/*");
context.addFilterMap(map);
tomcat.start();
while (true) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private static Filter getJerseyFilter() {
final ResourceConfig config = new ResourceConfig()
.register(new HelloResource(new Service()))
.register(JspMvcFeature.class)
.property(ServletProperties.FILTER_FORWARD_ON_404, true);
return new ServletContainer(config);
}
public static class Service {
public String getMessage() {
return "Hello Tomcat!";
}
}
#Path("tomcat")
public static class HelloResource {
private final Service service;
public HelloResource (Service service) {
this.service = service;
}
#GET
public String get() {
return this.service.getMessage();
}
}
}
You seem to have a lot of unnecessary stuff going on. You have two different configurations. Pick one. The problem is caused by the package scanning, which is picking up the resource and trying to register it.
Just get rid of the web.xml and MyApplication and just use the ResourceConfig you're currently using in the main class. Then you can register the servlet programmatically using Jersey's ServletContainer which is both a Filter and a HttpServlet. So you don't need the web.xml to configure Jersey as Filter. The ServletContainer is already a Filter
new SevletContainer(youResourceConfig);
I'm not too familiar with Tomcat embedded so I can't say how to register filters, but I'm sure a quick search will find you the answer. Just register the ServletContainer as a filter.
The jersey.config.servlet.filter.forwardOn404 init-param can also be configured with the filter registration. Or you can just configure it with the ResourceConfig, with its property method
resourceConfig.property("jersey.config.servlet.filter.forwardOn404", true);
Or better yet, use the constant
property(ServletProperties.FILTER_FORWARD_ON_404, true);
UPDATE
Here is a complete setup (based on your example) that works.
import org.apache.catalina.Context;
import org.apache.catalina.servlets.DefaultServlet;
import org.apache.catalina.startup.Tomcat;
import org.apache.tomcat.util.descriptor.web.FilterDef;
import org.apache.tomcat.util.descriptor.web.FilterMap;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.mvc.jsp.JspMvcFeature;
import org.glassfish.jersey.servlet.ServletContainer;
import org.glassfish.jersey.servlet.ServletProperties;
import javax.servlet.Filter;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import java.io.File;
/**
* #author Paul Samsotha.
*/
public class Main {
public static void main(String... args) throws Exception {
Tomcat tomcat = new Tomcat();
tomcat.setPort(9000);
File base = new File(".");
Context context = tomcat.addContext("", base.getAbsolutePath());
Tomcat.addServlet(context, "default", new DefaultServlet());
context.addServletMapping("/*", "default");
final FilterDef def = new FilterDef();
final FilterMap map = new FilterMap();
def.setFilterName("jerseyFilter");
def.setFilter(getJerseyFilter());
context.addFilterDef(def);
map.setFilterName("jerseyFilter");
map.addURLPattern("/api/*");
context.addFilterMap(map);
tomcat.start();
while (true) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private static Filter getJerseyFilter() {
final ResourceConfig config = new ResourceConfig()
.register(new HelloResource(new Service()))
.register(JspMvcFeature.class)
.property(ServletProperties.FILTER_FORWARD_ON_404, true);
return new ServletContainer(config);
}
public static class Service {
public String getMessage() {
return "Hello Tomcat!";
}
}
#Path("tomcat")
public static class HelloResource {
private final Service service;
public HelloResource (Service service) {
this.service = service;
}
#GET
public String get() {
return this.service.getMessage();
}
}
}
A few changes I made:
Not sure why you are using Tomcat 7 Servlet API. I Changed that to the 8.x version of your other Tomcat dependencies.
I also excluded the Servlet API from the Jersey MVC dependency, as that pulls in an older 2.4 Servlet API
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-mvc-jsp</artifactId>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
I added a DefaultServlet to handle the pages. From testing (again I am not Tomcat expert), it seems this is required
With the example you should be able to GET
http://localhost:9000/api/tomcat
First, Thanks to peeskillet who solved my problem. I search on the net but I did not find the exact solution.
For better reference and understandability, I create a demo application on git-hub.
jersey-mvc-jsp-freemarker-with-embedded-tomcat
Application Used
Tomcat v8.x
Jersey v2.5.1
JSP
YML
Freemarker
HTML/Angular/JavaScript
final ResourceConfig config = new ResourceConfig()
.packages(Main.class.getPackage().getName())
.register(new Resource(new Core(), configuration)) // create instance of Resource and dynamically register
.register(JspMvcFeature.class) // register jspMVC
.register(FreemarkerMvcFeature.class) // register FreemarkerMVC
.property(ServletProperties.FILTER_FORWARD_ON_404, true);
return new ServletContainer(config);
I had a test case to test the jersey 2.x rest service.. But got NullPointerException.. Seems to me there is a jar issue between jsr311 and javax.ws.rs-api . I didn't find any jsr311 with any dependencies.. Not sure why the servlet is taking is refering jsr311.jar
Below are my code changes
HelloWorldServiceTest.java
package test;
import static org.junit.Assert.assertEquals;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Application;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
import org.glassfish.jersey.test.DeploymentContext;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.ServletDeploymentContext;
import org.glassfish.jersey.test.ServletDeploymentContext.Builder;
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
import org.glassfish.jersey.test.spi.TestContainerException;
import org.glassfish.jersey.test.spi.TestContainerFactory;
import org.junit.Test;
import com.mkyong.rest.HelloWorldService;
import rest.RestApplication;
public class HelloWorldServiceTest extends JerseyTest{
#Path("hello")
public static class HelloResource {
#GET
public String getHello() {
return "Hello World!";
}
}
#Override
protected Application configure() {
// TODO Auto-generated method stub
return new ResourceConfig(HelloWorldService.class );
}
#Override
protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
return new GrizzlyWebTestContainerFactory();
}
#Override
protected ServletDeploymentContext configureDeployment() {
return ServletDeploymentContext.forPackages(HelloWorldService.class.getPackage().getName()).build();
//return ServletDeploymentContext.forServlet(new ServletContainer(new ResourceConfig(HelloWorldService.class))).build();
}
#Test
public void testSingleNode() throws Exception {
final String hello = target("hello").path("Test").request().get(String.class);
System.out.println("Response"+ hello);
assertEquals("Jersey say : Test", hello);
}
}
pom.xml
<dependencies>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework</groupId>
<artifactId>jersey-test-framework-core</artifactId>
<version>2.13</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>2.13</version>
</dependency>
</dependencies>
Below is my exception i got
java.lang.NoSuchMethodError: org.glassfish.jersey.internal.util.collection.Values.lazy(Lorg/glassfish/jersey/internal/util/collection/Value;)Lorg/glassfish/jersey/internal/util/collection/Value;
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:346)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:372)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:218)
at org.glassfish.grizzly.servlet.FilterChainImpl.doFilter(FilterChainImpl.java:147)
at org.glassfish.grizzly.servlet.FilterChainImpl.invokeFilterChain(FilterChainImpl.java:106)
at org.glassfish.grizzly.servlet.ServletHandler.doServletService(ServletHandler.java:221)
at org.glassfish.grizzly.servlet.ServletHandler.service(ServletHandler.java:169)
at org.glassfish.grizzly.http.server.HttpHandler$1.run(HttpHandler.java:219)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
at java.lang.Thread.run(Unknown Source)