2012-11-30 26 views
5

Jersey: 1.12 mùa xuân: 3.11 JDK: 1.6.0_35 Tomcat: 6..0.33Jersey ;: Đăng ký Tiêm Instances ExceptionMapper qua SpringServlet

Tôi cố gắng để đăng ký trường ExceptionMapper cho một servlet Jersey được khởi tạo bởi một thùng chứa Spring IoC trong ngữ cảnh của một SpringServlet, và đang chạy vào olde cũ "Phạm vi của lớp thành phần X phải là một ngoại lệ" singleton trong quá trình khởi tạo servlet Jersey. Tôi không ở vị trí để đăng mã thực tế vào thời điểm này, vì vậy tôi sẽ cung cấp cho các yếu tố cần thiết để thực hiện để xem có điều gì đó rõ ràng nhảy vào một ai đó hay không hoặc tôi có thể chỉ ra một số tài liệu mà tôi có bỏ lỡ.

Các ExceptionMapper dụ về cơ bản là như sau:

// ... package definitions omitted ... 

@Provider 
@Singleton 
public class MyExceptionMapper 
    implements ExceptionMapper<MyException> 
{ 
    // ... injected attributes omitted ... 

    @Override 
    public Response toResponse(MyException exception) 
    { 
     // ... specific handling logic omitted ... 

     return Response.status(Status.BAD_REQUEST).entity(exception.getMessage()).build(); 
    } 
} 

Định nghĩa bean trong applicationContext.xml là như sau, mặc định là Singleton phạm vi (và thêm một phạm vi specifier rõ ràng dường như không thay đổi hành vi):

<bean id="myExceptionMapper" class="my.package.MyExceptionMapper" /> 

các mùa xuân bối cảnh loader nghe và cấu hình SpringServlet trong web.xml cơ bản soạn sẵn, và servlet sẽ được tải, khởi tạo và hoạt động đúng với bơm các thuộc tính khác khi đậu defin ition cho MyExceptionMapper được nhận xét trong tệp applicationContext.xml. Nhưng khi định nghĩa bean có mặt trong applicationContext.xml, tôi nhận đăng tin nhắn đến ảnh hưởng của:

SpringProviderFactory - Registering Spring bean, myExpectionMapper, of type my.package.MyExceptionMapper as a provider class 
SpringProviderFactory - Registering Spring bean, myServiceController, of type my.package.MyServiceController as a root resource class 
... other root resource classes loading ... 
SpringServlet - Exception occurred when initialization 
java.lang.RuntimeException: The scope of the component class my.package.MyExceptionMapper must be a singleton 
    at som.sun.jersey.core.spi.component.ioc.IoCProviderFactory.wrap(...) 

Tôi đã thử đặt MyExceptionMapper trong hệ thống phân cấp gói quét để được chọn của các SpringServlet trong quá trình khởi, và trong một phân cấp gói riêng biệt và kết quả không thay đổi.

Bất kỳ hỗ trợ hoặc hướng dẫn nào về điều này sẽ được đánh giá cao.

+0

Bạn đã kiểm tra lại rằng bạn đang sử dụng javax. inject.Singleton và javax.inject chú thích được kích hoạt trong mùa xuân? –

Trả lời

1

Được bật cùng một vấn đề với Spring 3.2.3 và tích hợp 2.3.1 Jersey.

gì làm việc cho tôi là sự kết hợp của hai:

  1. chú thích jersey @Provider lớp với @Service hoặc làm cho nó rõ ràng singleton trong xml app-bối cảnh

    @Service //implies a singleton-scope 
    @Provider 
    public class UnhandledExceptionMapper implements ExceptionMapper<Throwable> { 
    
        @Override 
        public Response toResponse(Throwable exception) { //... 
    
  2. Thêm gói chứa lớp nhà cung cấp để gói áo, tôi thích làm điều này trong lớp MyApplication:

    public class MyApplication extends ResourceConfig { 
    public MyApplication() { 
        packages("com.mycompany.api.controller", "com.mycompany.api.jersey"); 
          //.... 
        } 
    } 
    
1

tôi đã cùng một vấn đề, nhưng với một lớp MessageReaderWriterProvider:

package my.provider.package; 
... 
@Provider 
@Consumes({MediaType.APPLICATION_JSON, "text/json"}) 
@Produces({MediaType.APPLICATION_JSON, "text/json"}) 
public class ReRwProvider extends AbstractMessageReaderWriterProvider<Object> { 
... 
} 

Giải pháp là để thêm các gói của lớp này trong một thẻ init-param cho SpringServlet Jersey trong web.xml:

<init-param> 
    <param-name>com.sun.jersey.config.property.packages</param-name> 
    <param-value>my.provider.package</param-value> 
</init-param> 

Lưu ý rằng bạn không nên xác định bean này trong ngữ cảnh Mùa xuân của mình.

4

My ExceptionMapper s nằm dưới cấu trúc mà tôi đang thực hiện quét thành phần và tôi được chú thích đơn giản với @Component cho đăng ký Spring và @Provider cho Jersey.

quét thành phần của tôi chỉ trông giống như:

<context:component-scan base-package="com.company.web"/> 

ExceptionMapper trông khá nhiều như của bạn:

package com.mycompany.web.provider; 

import com.mycompany.exception.SpecialException; 
import com.mycompany.exception.Error; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Component; 
import javax.ws.rs.core.MediaType; 
import javax.ws.rs.core.Response; 
import javax.ws.rs.ext.ExceptionMapper; 
import javax.ws.rs.ext.Provider; 

@Provider 
@Component 
public class SpecialExceptionMapper implements ExceptionMapper<SpecialException> { 

    @Autowired 
    private MessageSource messageSource; 

    @Override 
    public Response toResponse(SpecialException exception) { 

     Error error = new Error(); 


     error.errorMessage = messageSource.getMessage(exception.getResourceBundleKey(), exception.getArgs()); 

     return Response.status(Response.Status.BAD_REQUEST). 
       entity(error). 
       type(MediaType.APPLICATION_JSON). 
       build(); 
    } 
} 
4

Thêm phạm vi một cách rõ ràng trong cấu hình mùa xuân đã làm các trick cho tôi:

<bean id="exceptionMapper" class="my.pkg.MyExceptionMapper" scope="singleton" /> 
+1

Được rồi, nó đã làm các trick, nhưng điều này có nghĩa là gì? Spring không xem xét tất cả các bean được định nghĩa trong XML như singleton theo mặc định? Tại sao chúng ta cần xác định rõ ràng điều này? – saratbeesa

0

Dường như với tôi rằng ExceptionMapper phải được định cấu hình là "hát leton "với mùa xuân.Nếu bạn muốn sử dụng cấu hình chú thích, bạn phải chú ý vì jersey cũng có chú thích "@Singleton" (với ý nghĩa khác của javax.inject.Singleton được giải thích bởi mùa xuân) Để tránh bất kỳ sự nhầm lẫn nào, tôi thích sử dụng spring @ Chú thích dịch vụ, ngụ ý một phạm vi đơn lẻ ... như vậy:

import org.springframework.stereotype.Service; 

import javax.ws.rs.core.Response; 
import javax.ws.rs.ext.ExceptionMapper; 
import javax.ws.rs.ext.Provider; 

@Service //implies a singleton-scope 
@Provider 
public class UnhandledExceptionMapper implements ExceptionMapper<Throwable> { 

    @Override 
    public Response toResponse(Throwable exception) { 
     return Response.status(Response.Status.INTERNAL_SERVER_ERROR) 
       .entity(new ErrorBean(false, exception.getMessage(), null)) 
       .build(); 
    } 
} 
0

Tôi cũng tìm thấy đôi khi coustom ExceptionMapper không hoạt động và không phải lúc nào cũng hoạt động hoặc không hoạt động.

vì vậy tôi gỡ lỗi mã nguồn của áo.

lớp: org.glassfish.jersey.server.ServerRuntime, methed: mapException

... 
final long timestamp = tracingLogger.timestamp(ServerTraceEvent.EXCEPTION_MAPPING); 
**ExceptionMapper mapper = runtime.exceptionMappers.findMapping(throwable);** 
if (mapper != null) { 
     request.getRequestEventBuilder().setExceptionMapper(mapper); 

... nếu mapper là null, coustom ExceptionMapper sẽ không hoạt động.

lớp: org.glassfish.jersey.internal.ExceptionMapperFactory methed: ExceptionMapperFactory

các ngoại lệ Mapper: (có hai ngoại lệ ánh xạ một cùng một ngoại lệ: java.lang.Exception)

org.glassfish.jersey .server.mvc.internal.ErrorTemplateExceptionMapper @ 6473fc2, lớp java.lang.Exception

...

com.baidu.ssp.web.ws.exception.BaseExceptionMapper @ 7a84639c, lớp java.lang.Exception

đó là vì trong MvcFeature:

@ Override public boolean configure (thức FeatureContext ngữ cảnh) { thức cấu hình config = context.getConfiguration();

if (!config.isRegistered(ErrorTemplateExceptionMapper.class)) { 
    context.register(ErrorTemplateExceptionMapper.class); 
    context.register(new MvcBinder()); 

    return true; 
} 

return false; 

} ErrorTemplateExceptionMapper cũng được thêm vào ExceptionMapper.

vì vậy tôi thay đổi loại genericity MapperException tùy chỉnh của tôi: ExceptionMapper để ExceptionMapper

có thể giải quyết của tôi là không phù hợp cho bạn, vấn đề chính là ExceptionMapper

Các vấn đề liên quan