Showing posts with label jaxrs. Show all posts
Showing posts with label jaxrs. Show all posts

Tuesday, August 30, 2016

Getting KeyCloakContext From ServletRequest

When REST APIs are protected with keycloak authentication, we might need to get user realm in the backend to get some user information.

In the ServletRequestFilter implementation,


public class ApplicationFilter implements Filter {

private Base64 decoder = new Base64(true);

        @Inject
ServletRequestHolder requestHolder;

@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
try {
checkAuthentication(req);
....
//TODO
}

/**
* Get the logged in user info from the request.
* @param request
*/
private void checkAuthentication(ServletRequest request) {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
KeycloakSecurityContext kContext = (KeycloakSecurityContext) httpServletRequest
.getAttribute(KeycloakSecurityContext.class.getName());
String bearerToken;

if (kContext != null) {

bearerToken = kContext.getTokenString();
String[] jwtToken = bearerToken.split("\\.");
byte[] decodedClaims = decoder.decode(jwtToken[1]);
JSONObject jsonObj = new JSONObject(new String(decodedClaims));
.....
//TODO
}

Thursday, July 7, 2016

JAX-RS Custom Exception Mapper

When the service(backend) throws any custom exception, using <javax.ws.rs.ext.ExceptionMapper> we can catch it , and send a relevant message to the client (/caller).

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

/**
 * Map the server exceptions to return to the client
 *
 */

@Provider
public class CustomJaxRsExceptionMapper implements ExceptionMapper {

@Override
     @Produces("application/json")
public Response toResponse(ServiceException e) {

          Map map = new HashMap();
  map.put("Exception", e.getMessage());

Response response = Response.status(500).entity(map).build();
return response;
}
}

Tuesday, July 5, 2016

RESTEASY003875: Unable to find a constructor that takes a String param or a valueOf() or fromString() method

The error[1] occurs when we use complex types in our GET querys.  JAXRS understands simple data types. If we use complex types, we might need to have our own (de)serialisation for the complex types.



import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import javax.money.Monetary;
import javax.ws.rs.ext.ParamConverter;
import javax.ws.rs.ext.ParamConverterProvider;
import javax.ws.rs.ext.Provider;

import org.javamoney.moneta.Money;

@Provider
public class MoneyConverterProvider  implements ParamConverterProvider {

    private final MoneyConverter converter = new MoneyConverter();

    @Override
    public ParamConverter getConverter(Class rawType, Type genericType, Annotation[] annotations) {
        if (!rawType.equals(Money.class)) return null;
        return (ParamConverter) converter
    }

    public class MoneyConverter implements ParamConverter {

        public Money fromString(String value) {
            if (value == null ||value.isEmpty()) return null
   
            return Money.of(new BigDecimal(value), Monetary.getCurrency("AUD"));
        }

        public String toString(Money value) {
            if (value == null) return "";
            return value.toString(); 
        }

    }


}

[1]


0:42:46,435 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 86) MSC000001: Failed to start service jboss.undertow.deployment.default-server.default-host./apidb: org.jboss.msc.service.StartException in service jboss.undertow.deployment.default-server.default-host./apidb: java.lang.RuntimeException: RESTEASY003875: Unable to find a constructor that takes a String param or a valueOf() or fromString() method for javax.ws.rs.QueryParam("money") on public javax.ws.rs.core.Response com.rest.autogen.SalesTransactionEndpoint.getItems(java.lang.Integer,java.lang.Integer,java.lang.String,java.lang.Long,java.lang.String, org.javamoney.moneta.Money) for basetype: org.javamoney.moneta.Money

at org.wildfly.extension.undertow.deployment.UndertowDeploymentService$1.run(UndertowDeploymentService.java:85)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
at org.jboss.threads.JBossThread.run(JBossThread.java:320)
Caused by: java.lang.RuntimeException: RESTEASY003875: Unable to find a constructor that takes a String param or a valueOf() or fromString() method for javax.ws.rs.QueryParam("money") on public javax.ws.rs.core.Response com.rest.autogen.SalesTransactionEndpoint.getItems(java.lang.Integer,java.lang.Integer,java.lang.String,java.lang.Long,java.lang.String,org.javamoney.moneta.Money) for basetype: org.javamoney.moneta.Money
at org.jboss.resteasy.core.StringParameterInjector.initialize(StringParameterInjector.java:220)
at org.jboss.resteasy.core.StringParameterInjector.(StringParameterInjector.java:64)
at org.jboss.resteasy.core.QueryParamInjector.(QueryParamInjector.java:30)
at org.jboss.resteasy.core.InjectorFactoryImpl.createParameterExtractor(InjectorFactoryImpl.java:86)
at org.jboss.resteasy.cdi.CdiInjectorFactory.createParameterExtractor(CdiInjectorFactory.java:52)
at org.jboss.resteasy.core.MethodInjectorImpl.(MethodInjectorImpl.java:44)
at org.jboss.resteasy.core.InjectorFactoryImpl.createMethodInjector(InjectorFactoryImpl.java:77)
at org.jboss.resteasy.cdi.CdiInjectorFactory.createMethodInjector(CdiInjectorFactory.java:58)
at org.jboss.resteasy.core.ResourceMethodInvoker.(ResourceMethodInvoker.java:99)
at org.jboss.resteasy.core.ResourceMethodRegistry.processMethod(ResourceMethodRegistry.java:281)
at org.jboss.resteasy.core.ResourceMethodRegistry.register(ResourceMethodRegistry.java:252)
at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:222)
at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:194)
at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:180)
at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:157)
at org.jboss.resteasy.core.ResourceMethodRegistry.addPerRequestResource(ResourceMethodRegistry.java:76)
at org.jboss.resteasy.spi.ResteasyDeployment.registration(ResteasyDeployment.java:434)
at org.jboss.resteasy.spi.ResteasyDeployment.start(ResteasyDeployment.java:245)
at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.init(ServletContainerDispatcher.java:113)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.init(HttpServletDispatcher.java:36)
at io.undertow.servlet.core.LifecyleInterceptorInvocation.proceed(LifecyleInterceptorInvocation.java:117)
at org.wildfly.extension.undertow.security.RunAsLifecycleInterceptor.init(RunAsLifecycleInterceptor.java:78)
at io.undertow.servlet.core.LifecyleInterceptorInvocation.proceed(LifecyleInterceptorInvocation.java:103)
at io.undertow.servlet.core.ManagedServlet$DefaultInstanceStrategy.start(ManagedServlet.java:231)
at

io.undertow.servlet.core.ManagedServlet.createServlet(ManagedServlet.java:132)
at io.undertow.servlet.core.DeploymentManagerImpl.start(DeploymentManagerImpl.java:526)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.startContext(UndertowDeploymentService.java:101)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentService$1.run(UndertowDeploymentService.java:82)