Creating a simple mock json service in java

(Symeon Mattes) #1

Hi,

Lagom seems to be interesting but I’m having hard time to make something simple. It seems that I haven’t understood how it works and the hello world example, although it works, I don’t understand how to use it.

I’m trying to create a simple restful service that takes at its header two parameters and produces a json object. For instance in the MyService.java I have:

public interface BookService extends Service {

ServiceCall<NotUsed, String> getAllBook();

/**
 * @return
 */
@Override
default Descriptor descriptor() {

    return named("book").withCalls(
            restCall(GET, "/api/get-all-book", this::getAllBook)
    ).withAutoAcl(true);
}

}

Then in BookServiceImpl I have:

public class BookServiceImpl implements BookService {

private final PersistentEntityRegistry persistentEntityRegistry;

/**
 * @param registry
 * @param readSide
 * @param session
 */
@Inject
public BookServiceImpl(final PersistentEntityRegistry registry, ReadSide readSide, CassandraSession session) {
    this.persistentEntityRegistry = registry;

    persistentEntityRegistry.register(BookEntity.class);
    readSide.register(BookEventProcessor.class);
}


@Override
public ServiceCall<NotUsed, String> getAllBook() {
    return request -> {

        JSONObject myBook= new JSONObject();
        myBook.put("name","BookName");
        myBook.put("description","A description");
        myBook.put("price","$16");
        myBook.put("status","available");

       //how do I return JSONBject.toString()
    };
}

And then how do I put headers parameters? Some documentation that explains basics would be very helpful.

Thanks in advance

(Alan Klikic) #2

Hi,

You can check Online Auction Java example.

  1. it is not required to manually create json. You can specify Pojo as return object and default JSON serializator will create JSON automatically. Check this

  2. for extracting request headers you can use HeaderFilter. You need to set it in you service descriptor and prepare it for usage in implementation. Usage in implementation

Hope this helps.

Br,
Alan

(Symeon Mattes) #3

Hi Alan,

Thanks for your reply. For the headers is there any easier way? It seems that it’s quite complicated the way it’s being done. I have found this but I couldn’t find a working example. What I would like to do is take a token from the header, verify that the token is valid, if not send a json with error, if yes then send a json object with data.

Thanks

(Alan Klikic) #4

Hi,

you can do something like this:

public static <Request, Response> ServerServiceCall<Request, Response> validateHeader(
			Function<Boolean, ? extends ServerServiceCall<Request, Response>> serviceCall, String headerName) {
		return HeaderServiceCall.compose(requestHeader -> {
			Optional<String> headerValue = requestHeader.getHeader(headerName);
			if(!headerValue.isPresent()) 
				return serviceCall.apply(false);
			//TODO do some additional validation
			return serviceCall.apply(true);
			
		});
	}

In service implementation you would use it like this:

    @Value
	public static class ReturnPojo{
		String errorMsg;
		String content;
		public static ReturnPojo error(String errorMsg) {
			return new ReturnPojo(errorMsg, null);
		}
		public static ReturnPojo of(String content) {
			return new ReturnPojo(null, content);
		}
	}
	public ServiceCall<NotUsed, ReturnPojo> get() {
		return validateHeader(valid -> request ->  {
			if(!valid)
				return ReturnPojo.error("Header not valid");
			if(valid) {
				//TODO get Pojo
				return ReturnPojo.of("My content");
			}
		},"Authentication-Header");
		
	}

Hope this helps.

BR,
Alan

(Alan Klikic) #5

You can also supply validation function instead of headerName.
I use similar approach for JWT validation. If JWT is not valid I throw com.lightbend.lagom.javadsl.api.transport.Forbidden.