Add template for assignment 2
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
<?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>
|
||||
|
||||
<parent>
|
||||
<groupId>at.ac.tuwien.infosys.dst</groupId>
|
||||
<artifactId>dst</artifactId>
|
||||
<version>2021.1</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>ass2-service-api</artifactId>
|
||||
|
||||
<name>DST :: Assignment 2 :: Service :: API</name>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.grpc</groupId>
|
||||
<artifactId>grpc-protobuf</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.grpc</groupId>
|
||||
<artifactId>grpc-stub</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<extensions>
|
||||
<extension>
|
||||
<groupId>kr.motd.maven</groupId>
|
||||
<artifactId>os-maven-plugin</artifactId>
|
||||
</extension>
|
||||
</extensions>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.xolstice.maven.plugins</groupId>
|
||||
<artifactId>protobuf-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,24 @@
|
||||
package dst.ass2.service.api.auth;
|
||||
|
||||
public class AuthenticationException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public AuthenticationException() {
|
||||
}
|
||||
|
||||
public AuthenticationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public AuthenticationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public AuthenticationException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public AuthenticationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package dst.ass2.service.api.auth;
|
||||
|
||||
public interface IAuthenticationService {
|
||||
|
||||
/**
|
||||
* Attempts to authenticate the user with the given unique email address and the given password in plain text, by
|
||||
* checking the data against the records in the database. If the credentials are successfully authenticated, the
|
||||
* service generates a new authentication token which is stored (with the users email address) in-memory and then
|
||||
* returned.
|
||||
*
|
||||
* @param email the user email
|
||||
* @param password the password
|
||||
* @return a new authentication token
|
||||
* @throws NoSuchUserException if the given user was not found
|
||||
* @throws AuthenticationException if the credentials could not be authenticated
|
||||
*/
|
||||
String authenticate(String email, String password) throws NoSuchUserException, AuthenticationException;
|
||||
|
||||
/**
|
||||
* Changes the password of the given user in the database. Also updates the in-memory cache in a thread-safe way.
|
||||
*
|
||||
* @param email the user email
|
||||
* @param newPassword the new password in plain text.
|
||||
* @throws NoSuchUserException if the given user was not found
|
||||
*/
|
||||
void changePassword(String email, String newPassword) throws NoSuchUserException;
|
||||
|
||||
/**
|
||||
* Returns the user that is associated with this token. Returns null if the token does not exist.
|
||||
*
|
||||
* @param token an authentication token previously created via {@link #authenticate(String, String)}
|
||||
* @return the user's email address or null
|
||||
*/
|
||||
String getUser(String token);
|
||||
|
||||
/**
|
||||
* Checks whether the given token is valid (i.e., was issued by this service and has not been invalidated).
|
||||
*
|
||||
* @param token the token to validate
|
||||
* @return true if the token is valid, false otherwise
|
||||
*/
|
||||
boolean isValid(String token);
|
||||
|
||||
/**
|
||||
* Invalidates the given token, i.e., removes it from the cache. Returns false if the token did not exist.
|
||||
*
|
||||
* @param token the token to invalidate
|
||||
* @return true if the token existed and was successfully invalidated, false otherwise
|
||||
*/
|
||||
boolean invalidate(String token);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package dst.ass2.service.api.auth;
|
||||
|
||||
public class NoSuchUserException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public NoSuchUserException() {
|
||||
}
|
||||
|
||||
public NoSuchUserException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public NoSuchUserException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public NoSuchUserException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public NoSuchUserException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package dst.ass2.service.api.auth.rest;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import dst.ass2.service.api.auth.AuthenticationException;
|
||||
import dst.ass2.service.api.auth.NoSuchUserException;
|
||||
|
||||
/**
|
||||
* The IAuthenticationResource exposes parts of the {@code IAuthenticationService} as a RESTful interface.
|
||||
*/
|
||||
public interface IAuthenticationResource {
|
||||
|
||||
// TODO annotate the class and methods with the correct javax.ws.rs annotations
|
||||
|
||||
Response authenticate(String email, String password)
|
||||
throws NoSuchUserException, AuthenticationException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package dst.ass2.service.api.match;
|
||||
|
||||
import dst.ass2.service.api.trip.InvalidTripException;
|
||||
import dst.ass2.service.api.trip.MoneyDTO;
|
||||
import dst.ass2.service.api.trip.TripDTO;
|
||||
|
||||
/**
|
||||
* An implementation of this interface is provided to you by the application.
|
||||
*/
|
||||
public interface IMatchingService {
|
||||
|
||||
/**
|
||||
* The passed trip needs at least the following properties set: riderId, pickup, destination and fare
|
||||
*
|
||||
* @param trip the trip the MatchingService will calculate a fare for
|
||||
* @return the proposed fare for the given trip
|
||||
* @throws InvalidTripException in case the route cannot be calculated
|
||||
*/
|
||||
MoneyDTO calculateFare(TripDTO trip) throws InvalidTripException;
|
||||
|
||||
/**
|
||||
* Puts the trip into the queue for driver matching.
|
||||
* The trip with the specified ID needs at least the following properties set:
|
||||
* riderId, pickup, destination and fare
|
||||
*
|
||||
* @param tripId
|
||||
*/
|
||||
void queueTripForMatching(Long tripId);
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package dst.ass2.service.api.trip;
|
||||
|
||||
public class DriverNotAvailableException extends Exception {
|
||||
|
||||
public DriverNotAvailableException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public DriverNotAvailableException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package dst.ass2.service.api.trip;
|
||||
|
||||
/**
|
||||
* Exception indicating that a resource that was trying to be accessed does not exist.
|
||||
*/
|
||||
public class EntityNotFoundException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public EntityNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public EntityNotFoundException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package dst.ass2.service.api.trip;
|
||||
|
||||
public interface ITripService {
|
||||
|
||||
/**
|
||||
* Creates and persists a Trip, sets the state to CREATED and calculates an initial fare estimation for
|
||||
* the route 'pickupId - destinationId'
|
||||
*
|
||||
* @param riderId the id of the rider, who is planning a trip
|
||||
* @param pickupId the id of the pickupId location
|
||||
* @param destinationId the id of the destinationId location
|
||||
* @return a TripDTO corresponding to the persisted Trip and includes the fare (null if route is invalid)
|
||||
* @throws EntityNotFoundException if the rider or one of the locations doesn't exist
|
||||
*/
|
||||
TripDTO create(Long riderId, Long pickupId, Long destinationId) throws EntityNotFoundException;
|
||||
|
||||
|
||||
/**
|
||||
* Confirms the given trip (i.e., sets the state of the corresponding trip to QUEUED and
|
||||
* puts it into the queue for matching), if possible (i.e., the trip is still in CREATED state)
|
||||
*
|
||||
* @param tripId the trip to confirm
|
||||
* @throws EntityNotFoundException if the trip cannot be found
|
||||
* @throws IllegalStateException in case the trip is not in state CREATED or the rider is null
|
||||
* @throws InvalidTripException in case the fare couldn't be estimated
|
||||
*/
|
||||
void confirm(Long tripId) throws EntityNotFoundException, IllegalStateException, InvalidTripException;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a match for the given trip and sets the trip's state to MATCHED, if possible (i.e., if the trips is
|
||||
* QUEUED). Rolls back transaction in case something goes wrong and re-queues the trip for a new match.
|
||||
* You can assume that the locations (pickup, destination and stops) haven't been deleted and will not be deleted
|
||||
* during the execution of this method.
|
||||
*
|
||||
* @param tripId the id of the trip the match will be created for
|
||||
* @param match the match, containing the driver, the vehicle and the fare
|
||||
* @throws EntityNotFoundException in case one of the following doesn't exist anymore: trip, driver or
|
||||
* vehicle
|
||||
* @throws DriverNotAvailableException in case the driver was assigned in the meantime to another customer
|
||||
* @throws IllegalStateException in case the rider of the trip is null or the trip is not in QUEUED state
|
||||
*/
|
||||
void match(Long tripId, MatchDTO match) throws EntityNotFoundException, DriverNotAvailableException, IllegalStateException;
|
||||
|
||||
|
||||
/**
|
||||
* Completes the trip (i. e., persists a TripInfo object and set the trips state to COMPLETED)
|
||||
*
|
||||
* @param tripId the id of the trip to complete
|
||||
* @param tripInfoDTO the tripInfo to persist
|
||||
* @throws EntityNotFoundException in case the trip doesn't exist
|
||||
*/
|
||||
void complete(Long tripId, TripInfoDTO tripInfoDTO) throws EntityNotFoundException;
|
||||
|
||||
|
||||
/**
|
||||
* Cancels the given trip (i.e., sets the state to cancelled)
|
||||
*
|
||||
* @param tripId the trip to cancel
|
||||
* @throws EntityNotFoundException in case the trip doesn't exist
|
||||
*/
|
||||
void cancel(Long tripId) throws EntityNotFoundException;
|
||||
|
||||
|
||||
/**
|
||||
* Adds the location as a stop if possible (i.e., if the referenced trip is still in the CREATED state and
|
||||
* the given location is not already in the list of stops.)
|
||||
* As a side effect, the list of the passed TripDTO is modified and the fare freshly estimated.
|
||||
* In case the the estimation fails, sets the fare to null.
|
||||
*
|
||||
* You can assume that the passed TripDTO and the Trip entity have the same values
|
||||
* @param trip the trip
|
||||
* @param locationId the location
|
||||
* @return true if the stop was added, otherwise false
|
||||
* @throws EntityNotFoundException in case the location or trip doesn't exist
|
||||
* @throws IllegalStateException in case the trip isn't longer in the CREATED state
|
||||
*/
|
||||
boolean addStop(TripDTO trip, Long locationId) throws EntityNotFoundException, IllegalStateException;
|
||||
|
||||
|
||||
/**
|
||||
* Removes the location from the stops only (i.e., if the referenced trip is still in the CREATED state).
|
||||
* As a side effect, the list of the passed TripDTO is modified and the fare freshly estimated.
|
||||
* In case the the estimation fails, sets the fare to null.
|
||||
*
|
||||
* You can assume that the passed TripDTO and the Trip entity have the same values
|
||||
* @param trip the trip
|
||||
* @param locationId the location to remove
|
||||
* @return true if the trip was removed, otherwise false (for example when the location wasn't added to the stops)
|
||||
* @throws EntityNotFoundException in case the location or trip doesn't exist
|
||||
* @throws IllegalStateException in case the trip isn't longer in the CREATED state
|
||||
*/
|
||||
boolean removeStop(TripDTO trip, Long locationId) throws EntityNotFoundException, IllegalStateException;
|
||||
|
||||
|
||||
/**
|
||||
* Removes the trip with the given id.
|
||||
*
|
||||
* @param tripId the id of the trip to remove
|
||||
* @throws EntityNotFoundException in case the trip doesn't exist
|
||||
*/
|
||||
void delete(Long tripId) throws EntityNotFoundException;
|
||||
|
||||
|
||||
/**
|
||||
* Finds the trip with the given id and returns it as DTO, including the latest fare estimation.
|
||||
*
|
||||
* @param tripId the id of the trip
|
||||
* @return if found the DTO, otherwise null
|
||||
*/
|
||||
TripDTO find(Long tripId);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dst.ass2.service.api.trip;
|
||||
|
||||
public class InvalidTripException extends Exception {
|
||||
public InvalidTripException() {
|
||||
}
|
||||
|
||||
public InvalidTripException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package dst.ass2.service.api.trip;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class MatchDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long driverId;
|
||||
private Long vehicleId;
|
||||
|
||||
private MoneyDTO fare;
|
||||
|
||||
public Long getDriverId() {
|
||||
return driverId;
|
||||
}
|
||||
|
||||
public void setDriverId(Long driverId) {
|
||||
this.driverId = driverId;
|
||||
}
|
||||
|
||||
public Long getVehicleId() {
|
||||
return vehicleId;
|
||||
}
|
||||
|
||||
public void setVehicleId(Long vehicleId) {
|
||||
this.vehicleId = vehicleId;
|
||||
}
|
||||
|
||||
|
||||
public MoneyDTO getFare() {
|
||||
return fare;
|
||||
}
|
||||
|
||||
public void setFare(MoneyDTO fare) {
|
||||
this.fare = fare;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package dst.ass2.service.api.trip;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MoneyDTO {
|
||||
|
||||
private String currency;
|
||||
private BigDecimal value;
|
||||
|
||||
public String getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
|
||||
public void setCurrency(String currency) {
|
||||
this.currency = currency;
|
||||
}
|
||||
|
||||
public BigDecimal getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(BigDecimal value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
MoneyDTO moneyDTO = (MoneyDTO) o;
|
||||
return Objects.equals(getCurrency(), moneyDTO.getCurrency()) &&
|
||||
Objects.equals(getValue(), moneyDTO.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getCurrency(), getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MoneyDTO{" +
|
||||
"currency='" + currency + '\'' +
|
||||
", value=" + value +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package dst.ass2.service.api.trip;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class TripDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long id;
|
||||
private Long riderId;
|
||||
private Long pickupId;
|
||||
private Long destinationId;
|
||||
private List<Long> stops;
|
||||
private MoneyDTO fare;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getRiderId() {
|
||||
return riderId;
|
||||
}
|
||||
|
||||
public void setRiderId(Long riderId) {
|
||||
this.riderId = riderId;
|
||||
}
|
||||
|
||||
public Long getPickupId() {
|
||||
return pickupId;
|
||||
}
|
||||
|
||||
public void setPickupId(Long pickupId) {
|
||||
this.pickupId = pickupId;
|
||||
}
|
||||
|
||||
public Long getDestinationId() {
|
||||
return destinationId;
|
||||
}
|
||||
|
||||
public void setDestinationId(Long destinationId) {
|
||||
this.destinationId = destinationId;
|
||||
}
|
||||
|
||||
public List<Long> getStops() {
|
||||
if (stops == null) {
|
||||
stops = new LinkedList<>();
|
||||
}
|
||||
return stops;
|
||||
}
|
||||
|
||||
public void setStops(List<Long> stops) {
|
||||
this.stops = stops;
|
||||
}
|
||||
|
||||
public MoneyDTO getFare() {
|
||||
return fare;
|
||||
}
|
||||
|
||||
public void setFare(MoneyDTO fare) {
|
||||
this.fare = fare;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package dst.ass2.service.api.trip;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class TripInfoDTO {
|
||||
|
||||
private Double distance;
|
||||
private Date completed;
|
||||
private MoneyDTO fare;
|
||||
|
||||
public Double getDistance() {
|
||||
return distance;
|
||||
}
|
||||
|
||||
public void setDistance(Double distance) {
|
||||
this.distance = distance;
|
||||
}
|
||||
|
||||
public Date getCompleted() {
|
||||
return completed;
|
||||
}
|
||||
|
||||
public void setCompleted(Date completed) {
|
||||
this.completed = completed;
|
||||
}
|
||||
|
||||
|
||||
public MoneyDTO getFare() {
|
||||
return fare;
|
||||
}
|
||||
|
||||
public void setFare(MoneyDTO fare) {
|
||||
this.fare = fare;
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package dst.ass2.service.api.trip.rest;
|
||||
|
||||
import dst.ass2.service.api.trip.*;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
|
||||
/**
|
||||
* This interface exposes the {@code ITripService} as a RESTful interface.
|
||||
*/
|
||||
public interface ITripServiceResource {
|
||||
|
||||
// TODO annotate the class and methods with the correct javax.ws.rs annotations
|
||||
|
||||
Response createTrip(Long riderId, Long pickupId, Long destinationId)
|
||||
throws EntityNotFoundException, InvalidTripException;
|
||||
|
||||
Response confirm(Long tripId) throws EntityNotFoundException, InvalidTripException;
|
||||
|
||||
Response getTrip(Long tripId) throws EntityNotFoundException;
|
||||
|
||||
Response deleteTrip(Long tripId) throws EntityNotFoundException;
|
||||
|
||||
Response addStop(Long tripId, Long locationId) throws InvalidTripException, EntityNotFoundException;
|
||||
|
||||
Response removeStop(Long tripId, Long locationId) throws InvalidTripException, EntityNotFoundException;
|
||||
|
||||
Response match(Long tripId, MatchDTO matchDTO) throws EntityNotFoundException, DriverNotAvailableException;
|
||||
|
||||
Response complete(Long tripId, TripInfoDTO tripInfoDTO) throws EntityNotFoundException;
|
||||
|
||||
Response cancel(Long tripId) throws EntityNotFoundException;
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
syntax = "proto3";
|
||||
|
||||
// TODO implement authentication service
|
||||
@@ -0,0 +1,66 @@
|
||||
package dst.ass2.proto.auth;
|
||||
|
||||
import io.grpc.MethodDescriptor;
|
||||
import io.grpc.ServiceDescriptor;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.hasItems;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
public class ProtoSpecificationTest {
|
||||
|
||||
private ClassLoader cl;
|
||||
public static final String SERVICE_NAME = "dst.ass2.service.api.auth.proto.AuthService";
|
||||
public static final String GRPC_CLASS_NAME = SERVICE_NAME + "Grpc";
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
cl = ProtoSpecificationTest.class.getClassLoader();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generatedClass_exists() throws Exception {
|
||||
try {
|
||||
cl.loadClass(GRPC_CLASS_NAME);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new AssertionError("Classpath did not contain expected gRPC service class", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generatedClass_hasMethods() throws Exception {
|
||||
assertThat(getMethodDescriptors().keySet(), hasItems(
|
||||
SERVICE_NAME + "/authenticate",
|
||||
SERVICE_NAME + "/validateToken"
|
||||
));
|
||||
}
|
||||
|
||||
private Map<String, MethodDescriptor> getMethodDescriptors() throws ClassNotFoundException {
|
||||
return getMethodDescriptors(getServiceDescriptor(cl.loadClass(GRPC_CLASS_NAME)));
|
||||
}
|
||||
|
||||
private Map<String, MethodDescriptor> getMethodDescriptors(ServiceDescriptor sd) {
|
||||
return sd.getMethods().stream()
|
||||
.collect(Collectors.toMap(
|
||||
MethodDescriptor::getFullMethodName,
|
||||
Function.identity()
|
||||
));
|
||||
}
|
||||
|
||||
private ServiceDescriptor getServiceDescriptor(Class<?> grpcClass) {
|
||||
try {
|
||||
Method getServiceDescriptor = grpcClass.getDeclaredMethod("getServiceDescriptor");
|
||||
getServiceDescriptor.setAccessible(true);
|
||||
return (ServiceDescriptor) getServiceDescriptor.invoke(null);
|
||||
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
|
||||
throw new RuntimeException("Error finding service descriptor in " + grpcClass.getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user