-
Notifications
You must be signed in to change notification settings - Fork 22
refactor: enforce clean layer separation across repository, service, and controller #216
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
68ad08e
2def995
074f9d6
6c44109
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package org.phoebus.channelfinder.exceptions; | ||
|
|
||
| public class StorageException extends RuntimeException { | ||
|
|
||
| public StorageException(String message) { | ||
| super(message); | ||
| } | ||
|
|
||
| public StorageException(String message, Throwable cause) { | ||
| super(message, cause); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -57,20 +57,16 @@ | |
| import org.phoebus.channelfinder.entity.Scroll; | ||
| import org.phoebus.channelfinder.entity.SearchResult; | ||
| import org.phoebus.channelfinder.entity.Tag; | ||
| import org.phoebus.channelfinder.exceptions.ChannelValidationException; | ||
| import org.phoebus.channelfinder.exceptions.StorageException; | ||
| import org.springframework.beans.factory.annotation.Qualifier; | ||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.context.annotation.Configuration; | ||
| import org.springframework.data.repository.CrudRepository; | ||
| import org.springframework.http.HttpStatus; | ||
| import org.springframework.stereotype.Repository; | ||
| import org.springframework.util.LinkedMultiValueMap; | ||
| import org.springframework.util.MultiValueMap; | ||
| import org.springframework.web.server.ResponseStatusException; | ||
|
|
||
| // Jackson 2 required by elasticsearch-java 8.x JacksonJsonpMapper — migrate with ES 9 | ||
|
|
||
| @Repository | ||
| @Configuration | ||
| public class ChannelRepository implements CrudRepository<Channel, String> { | ||
|
|
||
| private static final Logger logger = Logger.getLogger(ChannelRepository.class.getName()); | ||
|
|
@@ -126,7 +122,7 @@ public Channel index(Channel channel) { | |
| } catch (Exception e) { | ||
| String message = MessageFormat.format(TextUtil.FAILED_TO_INDEX_CHANNEL, channel.toLog()); | ||
| logger.log(Level.SEVERE, message, e); | ||
| throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); | ||
| throw new StorageException(message, e); | ||
| } | ||
| return null; | ||
| } | ||
|
|
@@ -176,8 +172,7 @@ channel, new JacksonJsonpMapper(objectMapper))))) | |
| } catch (IOException e) { | ||
| String message = MessageFormat.format(TextUtil.FAILED_TO_INDEX_CHANNELS, chunk); | ||
| logger.log(Level.SEVERE, message, e); | ||
| throw new ResponseStatusException( | ||
| HttpStatus.INTERNAL_SERVER_ERROR, message, null); | ||
| throw new StorageException(message, e); | ||
| } | ||
| return Collections.emptyList(); | ||
| })); | ||
|
|
@@ -218,7 +213,7 @@ public Channel save(String channelName, Channel channel) { | |
| } catch (Exception e) { | ||
| String message = MessageFormat.format(TextUtil.FAILED_TO_INDEX_CHANNEL, channel.toLog()); | ||
| logger.log(Level.SEVERE, message, e); | ||
| throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); | ||
| throw new StorageException(message, e); | ||
| } | ||
| return null; | ||
| } | ||
|
|
@@ -310,8 +305,7 @@ public <S extends Channel> Iterable<S> saveAll(Iterable<S> channels) { | |
| String message = | ||
| MessageFormat.format(TextUtil.FAILED_TO_INDEX_CHANNELS, channels); | ||
| logger.log(Level.SEVERE, message, e); | ||
| throw new ResponseStatusException( | ||
| HttpStatus.INTERNAL_SERVER_ERROR, message, null); | ||
| throw new StorageException(message, e); | ||
| } | ||
| return Collections.emptyList(); | ||
| })); | ||
|
|
@@ -354,7 +348,7 @@ public Optional<Channel> findById(String channelName) { | |
| } catch (ElasticsearchException | IOException e) { | ||
| String message = MessageFormat.format(TextUtil.FAILED_TO_FIND_CHANNEL, channelName); | ||
| logger.log(Level.SEVERE, message, e); | ||
| throw new ResponseStatusException(HttpStatus.NOT_FOUND, message, null); | ||
| throw new StorageException(message, e); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -383,8 +377,7 @@ public boolean existsByIds(List<String> channelIds) { | |
| .containsAll(channelIds); | ||
| } catch (ElasticsearchException | IOException e) { | ||
| logger.log(Level.SEVERE, TextUtil.FAILED_TO_FIND_ALL_CHANNELS, e); | ||
| throw new ResponseStatusException( | ||
| HttpStatus.INTERNAL_SERVER_ERROR, TextUtil.FAILED_TO_FIND_ALL_CHANNELS, null); | ||
| throw new StorageException(TextUtil.FAILED_TO_FIND_ALL_CHANNELS, e); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -404,7 +397,7 @@ public boolean existsById(String channelName) { | |
| String message = | ||
| MessageFormat.format(TextUtil.FAILED_TO_CHECK_IF_CHANNEL_EXISTS, channelName); | ||
| logger.log(Level.SEVERE, message, e); | ||
| throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); | ||
| throw new StorageException(message, e); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -440,14 +433,13 @@ public List<Channel> findAllById(Iterable<String> channelIds) { | |
| return response.hits().hits().stream().map(Hit::source).collect(Collectors.toList()); | ||
| } catch (ElasticsearchException | IOException e) { | ||
| logger.log(Level.SEVERE, TextUtil.FAILED_TO_FIND_ALL_CHANNELS, e); | ||
| throw new ResponseStatusException( | ||
| HttpStatus.INTERNAL_SERVER_ERROR, TextUtil.FAILED_TO_FIND_ALL_CHANNELS, null); | ||
| throw new StorageException(TextUtil.FAILED_TO_FIND_ALL_CHANNELS, e); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public long count() { | ||
| return this.count(new LinkedMultiValueMap<>()); | ||
| return this.count(Map.of()); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -468,7 +460,7 @@ public void deleteById(String channelName) { | |
| } catch (ElasticsearchException | IOException e) { | ||
| String message = MessageFormat.format(TextUtil.FAILED_TO_DELETE_CHANNEL, channelName); | ||
| logger.log(Level.SEVERE, message, e); | ||
| throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); | ||
| throw new StorageException(message, e); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -516,7 +508,7 @@ public void deleteAll() { | |
| * @param searchParameters channel search parameters | ||
| * @return matching channels | ||
| */ | ||
| public SearchResult search(MultiValueMap<String, String> searchParameters) { | ||
| public SearchResult search(Map<String, List<String>> searchParameters) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why replacing MultiValuedMap?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See commit message for that change:
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch, misleading commit message. I still think it is an improvement as it is pure Java, which I think generally is preferably for repo and service layers. I will fix the commit message for now.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Disagree. Why should a service layer be "pure Java"? Spring offers a lot of APIs that make perfect sense in a service layer. Or: it would be quite limiting to restrict a service layer to only JDK APIs.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fair point. To be more clear, I the benefit is that the signature is not tied to a Spring interface - even if Spring is used elsewhere in the same (or lower) layer(s) for other reasons. And I guess the counter-argument is that TBH I have no strong feelings about this particular change, so I can drop it if you prefer it one way over the other. |
||
| BuiltQuery builtQuery = getBuiltQuery(searchParameters); | ||
| Integer finalSize = builtQuery.size; | ||
| Integer finalFrom = builtQuery.from; | ||
|
|
@@ -527,7 +519,7 @@ public SearchResult search(MultiValueMap<String, String> searchParameters) { | |
| TextUtil.SEARCH_FAILED_CAUSE, | ||
| searchParameters, | ||
| "Max search window exceeded, use the " + scrollResourceUri + " api."); | ||
| throw new ResponseStatusException(HttpStatus.BAD_REQUEST, message); | ||
| throw new ChannelValidationException(message); | ||
| } | ||
|
|
||
| try { | ||
|
|
@@ -554,11 +546,11 @@ public SearchResult search(MultiValueMap<String, String> searchParameters) { | |
| String message = | ||
| MessageFormat.format(TextUtil.SEARCH_FAILED_CAUSE, searchParameters, e.getMessage()); | ||
| logger.log(Level.SEVERE, message, e); | ||
| throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, e); | ||
| throw new StorageException(message, e); | ||
| } | ||
| } | ||
|
|
||
| private BuiltQuery getBuiltQuery(MultiValueMap<String, String> searchParameters) { | ||
| private BuiltQuery getBuiltQuery(Map<String, List<String>> searchParameters) { | ||
| BoolQuery.Builder boolQuery = new BoolQuery.Builder(); | ||
| int size = esService.getES_QUERY_SIZE(); | ||
| int from = 0; | ||
|
|
@@ -726,7 +718,7 @@ private record BuiltQuery( | |
| * @param searchParameters channel search parameters | ||
| * @return count of the number of matches to the provided query | ||
| */ | ||
| public long count(MultiValueMap<String, String> searchParameters) { | ||
| public long count(Map<String, List<String>> searchParameters) { | ||
| BuiltQuery builtQuery = getBuiltQuery(searchParameters); | ||
|
|
||
| try { | ||
|
|
@@ -742,7 +734,7 @@ public long count(MultiValueMap<String, String> searchParameters) { | |
| String message = | ||
| MessageFormat.format(TextUtil.COUNT_FAILED_CAUSE, searchParameters, e.getMessage()); | ||
| logger.log(Level.SEVERE, message, e); | ||
| throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, e); | ||
| throw new StorageException(message, e); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -754,9 +746,7 @@ public long count(MultiValueMap<String, String> searchParameters) { | |
| * @return count of the number of matches to the provided query | ||
| */ | ||
| public long countByProperty(String propertyName, String propertyValue) { | ||
| MultiValueMap<String, String> params = new LinkedMultiValueMap<>(); | ||
| params.add(propertyName, propertyValue == null ? "*" : propertyValue); | ||
| return this.count(params); | ||
| return this.count(Map.of(propertyName, List.of(propertyValue == null ? "*" : propertyValue))); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -766,9 +756,7 @@ public long countByProperty(String propertyName, String propertyValue) { | |
| * @return count of the number of matches to the provided query | ||
| */ | ||
| public long countByTag(String tagName) { | ||
| MultiValueMap<String, String> params = new LinkedMultiValueMap<>(); | ||
| params.add("~tag", tagName); | ||
| return this.count(params); | ||
| return this.count(Map.of("~tag", List.of(tagName))); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -779,7 +767,7 @@ public long countByTag(String tagName) { | |
| * @param searchParameters channel search parameters | ||
| * @return next page with its cursor | ||
| */ | ||
| public Scroll scroll(String scrollId, MultiValueMap<String, String> searchParameters) { | ||
| public Scroll scroll(String scrollId, Map<String, List<String>> searchParameters) { | ||
| BuiltQuery builtQuery = getBuiltQuery(searchParameters); | ||
| try { | ||
| SearchRequest.Builder builder = | ||
|
|
@@ -800,7 +788,7 @@ public Scroll scroll(String scrollId, MultiValueMap<String, String> searchParame | |
| } catch (IOException | ElasticsearchException e) { | ||
| String message = | ||
| MessageFormat.format(TextUtil.SEARCH_FAILED_CAUSE, searchParameters, e.getMessage()); | ||
| throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, e); | ||
| throw new StorageException(message, e); | ||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feel like there should be a better name
RepositoryException?