Amdatu: How to make ExceptionMapper (#Provider) to work? - java

I'm trying to manage all my exceptions with an ExceptionMapper, as i saw in multiple documentation and examples. However, it doesn't seem to work, at least in my conditions.
I'm in a OSGI environment, using the Felix Witheboard pattern, with Amdatu Wink, so i don't have a web.xml and everything is supposed to be managed by itself.
I tried to register my ExceptionMapper as a service as i did with my web services, with no results.
#Component(immediate=true, provide={Object.class})
#Provider
public class SessionTimeoutExeptionHandler implements ExceptionMapper<SessionTimeoutException>{
public Response toResponse(SessionTimeoutException arg0) {
Response toReturn = Response.status(Status.FORBIDDEN)
.entity("session_timeout")
.build();
return toReturn;
};
}
Don't pay attention to the Response itself, i was just playing around.
My code is never called, how am i supposed to setup that provider?

You have to register the Provider in a javax.ws.rs.core.Application. That Application should be registered as a service with a higher service ranking than the default one created by the Amdatu Wink bundle.
The following is a working example.
The Exception Mapper itself:
#Provider
public class SecurityExceptionMapper implements ExceptionMapper<SecurityException>{
#Override
public Response toResponse(SecurityException arg0) {
return Response.status(403).build();
}
}
The Application:
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
public class MyApplication extends Application {
#Override
public Set<Object> getSingletons() {
Set<Object> s = new HashSet<Object>();
s.add(new JacksonJsonProvider());
s.add(new SecurityExceptionMapper());
return s;
}
}
Activator setting the service ranking property.
public class Activator extends DependencyActivatorBase{
#Override
public void destroy(BundleContext arg0, DependencyManager arg1) throws Exception {
}
#Override
public void init(BundleContext arg0, DependencyManager dm) throws Exception {
Properties props = new Properties();
props.put(Constants.SERVICE_RANKING, 100);
dm.add(createComponent().setInterface(Application.class.getName(), props).setImplementation(MyApplication.class));
}
}

Related

About apache Ignite service Implementation

If I have an interface
public interface TestService {
public String getSomething();
}
and a class
import org.apache.ignite.services.Service;
import org.apache.ignite.services.ServiceContext;
public class TestServiceImpl implements Service, TestService {
#Override
public void init(ServiceContext ctx) throws Exception {
}
#Override
public void execute(ServiceContext ctx) throws Exception {
}
#Override
public void cancel(ServiceContext ctx) {
}
#Override
public String getSomething() {
return "HelloWorld";
}
}
I deploy this service on ignite server nodes with
// Deploy services only on server nodes.
IgniteServices serverSvcs = ignite.services(ignite.cluster().forServers());
// Deploy cluster singleton.
serverSvcs.deployClusterSingleton("TestService", new TestServiceImpl());
And Ignite client node try to get the service
TestService testSvc = mIgnite.services().serviceProxy("TestService", TestService.class, false);
If the client node doesn't contain the "TestServiceImpl" class,
will catch exception with message:
"Failed to find class with given class loader for unmarshalling (make sure same versions of all classes are available on all nodes or enable peer-class-loading)",
Is it necessary that ignite client node must have the class TestServiceImpl ?
This was fixed already and the fix will be released in upcoming Ignite 1.6. In the meantime you can download the nightly build and check if it works for you: http://ignite.apache.org/community/contribute.html#nightly-builds

Custom Error Page in PlayFramework2.4.x

I did these and still can't see my custom page, please help,
Added MyGlobal.java extends GlobalSettings
Added onHandlerNotFound to override:
#Override
public F.Promise<Result> onHandlerNotFound(RequestHeader request) {
Logger.error("onHandlerNotFound!");
return Promise.<Result> pure(Results.internalServerError(views.html.page404.render()));
}
Added application.global = "MyGlobal" in application.conf
But nothing happends, play2.4.6 still runs out the default page from devNotFound.scala.html in playframework source folder of framework/play/src/main/scala/views/defaultpages/
Please help.
The way to do it in Play 2.4.x is to use an HttpErrorHandler as documented here:
https://www.playframework.com/documentation/2.4.x/JavaErrorHandling
You can just extends the DefaultHttpErrorHandler and add return your custom pages:
https://www.playframework.com/documentation/2.4.x/JavaErrorHandling#Extending-the-default-error-handler
https://www.playframework.com/documentation/2.4.x/api/java/play/http/DefaultHttpErrorHandler.html
Here is a full example, considering that you are trying to override the default 404 page:
package com.acme.controllers.handlers;
import play.*;
import play.api.OptionalSourceMapper;
import play.api.UsefulException;
import play.api.routing.Router;
import play.http.DefaultHttpErrorHandler;
import play.libs.F.*;
import play.mvc.Http.*;
import play.mvc.*;
import javax.inject.*;
public class ErrorHandler extends DefaultHttpErrorHandler {
#Inject
public ErrorHandler(Configuration configuration, Environment environment,
OptionalSourceMapper sourceMapper, Provider<Router> routes) {
super(configuration, environment, sourceMapper, routes);
}
#Override
protected Promise<Result> onNotFound(RequestHeader request, java.lang.String message) {
Logger.error("onHandlerNotFound!");
return Promise.pure(Results.internalServerError(views.html.page404.render()));
}
}
And then, you need to configure in your conf/application.conf like this:
play.http.errorHandler = "com.acme.controllers.handlers.ErrorHandler"
public class Global extends GlobalSettings {
#Override
public Promise<SimpleResult> onHandlerNotFound(RequestHeader request) {
return Promise.<SimpleResult>pure(internalServerError(views.html.page404.render()));
}
}
#Override
protected F.Promise<Result> onNotFound(RequestHeader request, String message) {
Logger.debug("onNotFound: " + message);
return Promise.<Result> pure(Results
.ok(views.html.admin.page404.render(request.method(), request.uri())));
}
Thanks for help, it really does work in dev env..
I already had the MyErrorHandler.java but not overriding the onNotFound function, because i was almost lost in the extending GlobalSettings's onHandlerNotFound.

NullPointer Exception while calling webservice in play framework

Anything wrong in this program ?
I am getting nullPointerException while calling web service in play framework in version 2.4.3.
package com.enkindle.box;
import javax.inject.Inject;
import play.libs.ws.WSClient;
/**
* #author thirumal
*
*/
public class Sample {
#Inject WSClient ws;
public static void main(String[] args) {
Sample sample = new Sample();
sample.callAPI();
}
public void callAPI() {
ws.url("www.thomas-bayer.com/sqlrest/CUSTOMER/").get();
}
}
The issue is that your Sample class is not available within the context of your dependency injection - I'm assuming Guice. There are a couple ways to tackle this but the easiest is to create a Sample interface and bind its implementation, SampleImpl, using Guice so that it will be available for injected dependencies. I'm going to assume that this gets spawned from a controller, so you could inject Sample into your controller and hit the callApi() method from there.
Controller:
public class SampleController extends Controller {
#Inject Sample sample;
public Promise<Result> apiCall() {
sample.callApi();
return promise(() -> ok());
}
}
Interface:
#ImplementedBy(SampleImpl.class)
public interface Sample {
public void callApi();
}
And the interface implementation:
public class SampleImpl implements Sample {
#Inject WSClient ws;
#Override
public void callApi() {
// ws should not be null
ws.url("www.thomas-bayer.com/sqlrest/CUSTOMER/").get();
}
}
Reference docs: https://www.playframework.com/documentation/2.4.x/JavaDependencyInjection#Binding-annotations

How to write Unit Test for this class using Jersey 2 test framework

I am trying to write unit test for a Rest api call which is having a POST method for adding a video file to web based application using Jersey2. Here is the signature of the method of my class(TemplateController.java) for which I want to write unit test:
#POST
#Path("/video/add")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response addVideoData(
#Context HttpServletRequest request,
AttachmentDTO attachmentDTO) {
...
}
Here is my test method of the test class (TemplateControllerUnitTestCase.java):
#Test
public void videoAdd_requestObjectIsNull_ResponseStatusIsOK() throws Exception {
// arrange
Builder builder = target("/target/video/add").request();
// action
final Response response = builder.post(Entity.entity(attachemntDTO, MediaType.APPLICATION_JSON));
// assertion
...
}
I'm able to pass the AttachmentDAO object to the TemplateController class from test class but unable to pass the request object which is becoming null in the method(addVideoData()) of the TemplateController.java class.
I'm using RequestHelper class which is a helper class for HttpServletRequest, so I want to pass an object of this class to the method(addVideoData()) using Jersey2 test framework.
You can use the HK2 capabilities of Jersey 2, that helps with Dependency Injection. Doing it this way, you can create a Factory for HttpServletRequest and return the mock from your RequestHelper. For example
public class HttpServletRequestFactory implements Factory<HttpServlet> {
#Override
public HttpServletRequest provide() {
return RequestHelper.getMockServletRequest();
}
#Override
public void dispose(HttpSession t) {
}
}
Then in your JerseyTest subclass, just register an AbstractBinder with the ResourceConfig. For example
#Override
public Application configure() {
ResourceConfig config = new ResourceConfig(...);
config.register(new AbstractBinder(){
#Override
public void configure() {
bindFactory(HttpServletRequestFactory.class).to(HttpServletRequest.class);
}
});
}
Another option
...is to not mock the HttpServletRequest at all, and use the actual HttpServletRequest. To do that, we need to configure the DeploymentContext as we override the getDeploymentContext(), and return a ServletDeploymentContext. You can see an example here and here. The first has also has an example of using a Factory, while the second show an example of how to configure based on web.xml settings. If you chose the case for mocking the HttpServletRequest, then you wouldn't need to override the getTestContainerFactory and configureDeployment as seen in the examples. Simply using the Application configure() override is enough, as long as nothing else is dependent on servlet features.
The examples in the link use
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>${jersey.version}</version>
</dependency>
Extra
Both the example I linked to are trying to take advantage of the Sevlet features. So I'll give a complete example of using a request mock.
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import org.glassfish.hk2.api.Factory;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Assert;
import org.junit.Test;
public class MockHttpSevletRequestTest extends JerseyTest {
#Path("http")
public static class HttpResource {
#GET
public Response getResponse(#Context HttpServletRequest request) {
return Response.ok(request.getMethod()).build();
}
}
#Override
public Application configure() {
ResourceConfig config = new ResourceConfig(HttpResource.class);
config.register(new AbstractBinder() {
#Override
public void configure() {
bindFactory(HttpServletRequestFactory.class)
.to(HttpServletRequest.class);
}
});
return config;
}
public static class HttpServletRequestFactory implements Factory<HttpServletRequest> {
#Override
public HttpServletRequest provide() {
return new MockHttpServletRequest();
}
#Override
public void dispose(HttpServletRequest t) {
}
}
#Test
public void test() {
String response = target("http").request().get(String.class);
System.out.println(response);
Assert.assertEquals("POST", response);
}
}
MockHttpServletRequest is simple a dummy implementation of HttpServletRequest where I only override one method getMethod() and always return POST. You can see from the result, that even though it's a get request, it still returns POST
public class MockHttpServletRequest implements HttpServletRequest {
#Override
public String getMethod() {
return "POST";
}
...
}

Using a custom hk2 InjectionResolver to inject application configuration

Kind of a follow up to my previous question. I'm trying to inject application configuration data using JSR-330 standard annotations and the HK2 framework bundled with jersey.
Ideally I'd like to create a custom InjectionResolver for the Named annotation, which will lookup the desired values in a Map or Properties object that I will populate from data read elsewhere. In my first attempt I've created an Application instance like
public class MyApplication extends ResourceConfig {
...
packages(MY_PACKAGES);
property(MY_CONFIG_PROPERTY, someValue);
register(new AbstractBinder() {
#Override
protected void configure() {
bind(ConfigurationInjectionResolver.class)
.to(new TypeLiteral<InjectionResolver<Named>>(){})
.in(Singleton.class)
}
});
}
and then my InjectionResolver looks like
public class ConfigurationInjectionResolver implements InjectionResolver<Named> {
#Context Application application;
#Override
public Object resolve(Injectee injectee, ServiceHandle<?> serviceHandle) {
// lookup data in application.getProperties();
}
}
My problem is that application.getProperties() is empty. Any idea what's wrong? Also, could I bind an instance of my Injector instead of binding the class? That way I could construct the instance passing my Map data as a parameter.
"My problem is that application.getProperties() is empty. Any idea what's wrong?
No. This actually works perfectly fine for me.
public class ConfigurationInjectionResolver implements InjectionResolver<Named> {
#Context
Application application;
#Override
public Object resolve(Injectee injectee, ServiceHandle<?> root) {
Named annotation = injectee.getParent().getAnnotation(Named.class);
Map<String, Object> props = application.getProperties();
String name = annotation.value();
System.out.println(props.get(name));
return props.get(name);
}
#Override
public boolean isConstructorParameterIndicator() { return false; }
#Override
public boolean isMethodParameterIndicator() { return false; }
}
#ApplicationPath("/rest")
public class JerseyApplication extends ResourceConfig {
public JerseyApplication() {
packages("jersey.startup.test");
property("hello.config", "Hello World Property");
register(new AbstractBinder() {
#Override
protected void configure() {
bind(ConfigurationInjectionResolver.class)
.to(new TypeLiteral<InjectionResolver<Named>>() {
}).in(Singleton.class);
}
});
}
}
Resource
#Path("/config")
public class ConfigResource {
#Named("hello.config")
String hello;
#GET
public Response getHello() {
return Response.ok(hello).build();
}
}
C:\>curl http://localhost:8080/test/rest/config
Hello World Property
Personally though, in this situation, I would create my own annotation, as to not override any existing functionality of the #Named annotation.
Another cool option
HK2 has a configuration extension, where you can load a Properties object from say a .properties file and and have those properties automatically injected with the #Configured annotation. I couldn't find any documentation on this, but there is an example usage of it in the HK2 source code examples.
Here's an example implementation
Required dependencies. Check the Jersey version and see what HK2 version it depends on. In my case Jersey 2.13 uses HK2 2.3.0-b10, so that should be the ${hk2.version}
<dependency>
<groupId>org.glassfish.hk2</groupId>
<artifactId>hk2-configuration-hub</artifactId>
<version>${hk2.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.hk2</groupId>
<artifactId>hk2-configuration-integration</artifactId>
<version>${hk2.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.hk2</groupId>
<artifactId>hk2-property-file</artifactId>
<version>${hk2.version}</version>
</dependency>
App config
#ApplicationPath("/rest")
public class JerseyApplication extends ResourceConfig {
#Inject
public JerseyApplication(ServiceLocator locator) {
packages("jersey.startup.test");
ServiceLocatorUtilities.addClasses(locator, ConfigResource.class);
try {
loadConfigurationProperties(locator);
} catch (IOException ex) {
Logger.getLogger(JerseyApplication.class.getName())
.log(Level.SEVERE, null, ex);
}
}
private void loadConfigurationProperties(ServiceLocator locator)
throws IOException {
ConfigurationUtilities.enableConfigurationSystem(locator);
PropertyFileUtilities.enablePropertyFileService(locator);
PropertyFileService propertyFileService
= locator.getService(PropertyFileService.class);
Properties props = new Properties();
URL url = getClass().getResource("/configuration.properties");
props.load(url.openStream());
PropertyFileHandle propertyFileHandle
= propertyFileService.createPropertyHandleOfAnyType();
propertyFileHandle.readProperties(props);
}
}
configuration.properties
AppConfiguration.App.hello=Hello Squirrel Property!
Resource
#Path("/config")
#ConfiguredBy("AppConfiguration")
public class ConfigResource {
#Configured
String hello;
#GET
public Response getHello() {
return Response.ok(hello).build();
}
}
C:\>curl http://localhost:8080/test/rest/config
Hello Squirrel Property!
Diclaimer: Since this feature isn't well documented, I am not sure if I have a good implementation here. It is just by trial and error. For instance this
ServiceLocatorUtilities.addClasses(locator, ConfigResource.class);
I feel shouldn't be necessary. It seems redundant, as I am already package scanning. So to explicitly add the ConfigResource to the locator context doesn't seem right to me.

Categories