Skip to content

Commit a3b5f8c

Browse files
committed
Merge branch 'hotfix-1.5.1'
2 parents 4b3fdde + e1e876f commit a3b5f8c

25 files changed

+126
-95
lines changed

pom.xml

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
<groupId>ubc.pavlab</groupId>
77
<artifactId>rdp</artifactId>
8-
<version>1.5.0</version>
8+
<version>1.5.1</version>
99

1010
<description>
1111
Registry for model organism researchers, developed for the Canadian Rare Disease Models &amp; Mechanisms Network.
@@ -28,7 +28,7 @@
2828
<parent>
2929
<groupId>org.springframework.boot</groupId>
3030
<artifactId>spring-boot-starter-parent</artifactId>
31-
<version>2.6.10</version>
31+
<version>2.6.12</version>
3232
</parent>
3333

3434
<dependencies>
@@ -108,7 +108,7 @@
108108
<dependency>
109109
<groupId>org.springdoc</groupId>
110110
<artifactId>springdoc-openapi-webmvc-core</artifactId>
111-
<version>1.6.9</version>
111+
<version>1.6.11</version>
112112
</dependency>
113113

114114
<!-- Database Migration -->

src/main/java/ubc/pavlab/rdp/controllers/AbstractSearchController.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ protected Map<URI, List<OntologyAvailability>> getOntologyAvailabilityByApiUri(
291291

292292
Map<URI, List<OntologyAvailability>> availability = new HashMap<>();
293293
for ( URI remoteHost : remoteResourceService.getApiUris() ) {
294-
List<OntologyAvailability> availabilities = new ArrayList<>();
294+
List<OntologyAvailability> availabilities = new ArrayList<>( termsByOntology.size() );
295295
// lookup origin and origin URL in all terms from all ontologies
296296
// when an ontology is not present, there are no terms returned and thus no way to determine the origin, so
297297
// we increase our chance by of finding something useful this way

src/main/java/ubc/pavlab/rdp/controllers/AdminController.java

+15-17
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ public Object updateRoles( @PathVariable User user, @RequestParam(required = fal
167167
}
168168
} catch ( RoleException e ) {
169169
redirectAttributes.addFlashAttribute( "message", e.getMessage() );
170-
redirectAttributes.addFlashAttribute( "error", true );
170+
redirectAttributes.addFlashAttribute( "error", Boolean.TRUE );
171171
}
172172
return "redirect:/admin/users/" + user.getId();
173173

@@ -361,9 +361,9 @@ public Object deleteOntology( @PathVariable(required = false) Ontology ontology,
361361
redirectAttributes.addFlashAttribute( "message", String.format( "The %s category has been deleted.", messageSource.getMessage( ontology.getResolvableTitle(), locale ) ) );
362362
return "redirect:/admin/ontologies";
363363
} catch ( DataIntegrityViolationException e ) {
364-
log.warn( String.format( "An administrator attempted to delete %s, but it failed: %s", ontology, e.getMessage() ) );
364+
log.warn( String.format( "An administrator attempted to delete %s, but it failed: %s", ontology.toString().replaceAll( "[\r\n]", "" ), e.getMessage() ) );
365365
modelAndView.setStatus( HttpStatus.BAD_REQUEST );
366-
modelAndView.addObject( "error", true );
366+
modelAndView.addObject( "error", Boolean.TRUE );
367367
modelAndView.addObject( "message", String.format( "The %s category could not be deleted because it is being used. Instead, you should deactivate it.", messageSource.getMessage( ontology.getResolvableTitle(), locale ) ) );
368368
}
369369
}
@@ -592,9 +592,9 @@ public void validate( Object target, Errors errors ) {
592592
.filter( row -> !row.isEmpty() )
593593
.map( SimpleOntologyTermForm::getTermId )
594594
.filter( termId -> !StringUtils.isEmpty( termId ) ) // empty or null term IDs are generated
595-
.collect( Collectors.groupingBy( t -> t, Collectors.counting() ) );
595+
.collect( Collectors.groupingBy( identity(), Collectors.counting() ) );
596596
if ( countsByTermId.values().stream().anyMatch( x -> x > 1 ) ) {
597-
errors.rejectValue( "ontologyTerms", "AdminController.SimpleOntologyForm.ontologyTerms.nonUniqueTermIds", "termId must be unique" );
597+
errors.rejectValue( "ontologyTerms", "AdminController.SimpleOntologyForm.ontologyTerms.nonUniqueTermIds" );
598598
}
599599

600600
// validate non-empty rows
@@ -643,19 +643,19 @@ public Object updateOntology( @PathVariable(required = false) Ontology ontology,
643643
return new ModelAndView( "admin/ontology", HttpStatus.BAD_REQUEST )
644644
.addAllObjects( defaultsForOntologyModelAndView( ontology ) )
645645
.addObject( "message", "The provided ontology cannot be updated because it lacks an external URL." )
646-
.addObject( "error", true );
646+
.addObject( "error", Boolean.TRUE );
647647
} else {
648648
Resource urlResource = ontologyService.resolveOntologyUrl( ontology.getOntologyUrl() );
649649
try ( Reader reader = new InputStreamReader( urlResource.getInputStream() ) ) {
650650
ontologyService.updateFromObo( ontology, reader );
651651
int numActivated = ontologyService.propagateSubtreeActivation( ontology );
652652
redirectAttributes.addFlashAttribute( "message", String.format( "Updated %s from %s. %d terms got activated via subtree propagation.", messageSource.getMessage( ontology.getResolvableTitle(), locale ), ontology.getOntologyUrl(), numActivated ) );
653653
} catch ( IOException | ParseException e ) {
654-
log.warn( String.format( "Failed to update ontology %s from administrative section.", ontology ), e );
654+
log.warn( String.format( "Failed to update ontology %s from administrative section.", ontology.toString().replaceAll( "[\r\n]", "" ) ), e );
655655
return new ModelAndView( "admin/ontology", HttpStatus.BAD_REQUEST )
656656
.addAllObjects( defaultsForOntologyModelAndView( ontology ) )
657657
.addObject( "message", String.format( "Failed to update %s: %s", messageSource.getMessage( ontology.getResolvableTitle(), locale ), e.getMessage() ) )
658-
.addObject( "error", true );
658+
.addObject( "error", Boolean.TRUE );
659659
}
660660
}
661661
return "redirect:/admin/ontologies/" + ontology.getId();
@@ -673,14 +673,12 @@ public Object importOntology( @Valid ImportOntologyForm importOntologyForm, Bind
673673
ontologyService.update( ontology );
674674
return "redirect:/admin/ontologies/" + ontology.getId();
675675
} catch ( OntologyNameAlreadyUsedException e ) {
676-
bindingResult.reject( "AdminController.ImportOntologyForm.ontologyWithSameNameAlreadyUsed", new String[]{ e.getOntologyName() },
677-
String.format( "An ontology with the same name '%s' is already used.", e.getOntologyName() ) );
676+
bindingResult.reject( "AdminController.ImportOntologyForm.ontologyWithSameNameAlreadyUsed", new String[]{ e.getOntologyName() }, null );
678677
return new ModelAndView( "admin/ontologies", HttpStatus.BAD_REQUEST )
679678
.addObject( "simpleOntologyForm", SimpleOntologyForm.withInitialRows() );
680679
} catch ( IOException | ParseException e ) {
681680
log.warn( String.format( "Failed to import ontology from submitted form: %s.", importOntologyForm ), e );
682-
bindingResult.reject( "AdminController.ImportOntologyForm.failedToParseOboFormat", new String[]{ importOntologyForm.getFilename(), e.getMessage() },
683-
String.format( "Failed to parse the ontology OBO format from %s: %s", importOntologyForm.getFilename(), e.getMessage() ) );
681+
bindingResult.reject( "AdminController.ImportOntologyForm.failedToParseOboFormat", new String[]{ importOntologyForm.getFilename(), e.getMessage() }, null );
684682
return new ModelAndView( "admin/ontologies", HttpStatus.INTERNAL_SERVER_ERROR )
685683
.addObject( "simpleOntologyForm", SimpleOntologyForm.withInitialRows() );
686684
}
@@ -711,7 +709,7 @@ public Object importReactomePathways( RedirectAttributes redirectAttributes ) {
711709
} catch ( ReactomeException e ) {
712710
log.error( "Failed to import Reactome pathways. Could this be an issue with the ontology configuration?", e );
713711
redirectAttributes.addFlashAttribute( "message", "Failed to import Reactome pathways: " + e.getMessage() + "." );
714-
redirectAttributes.addFlashAttribute( "error", true );
712+
redirectAttributes.addFlashAttribute( "error", Boolean.TRUE );
715713
return "redirect:/admin/ontologies";
716714
}
717715
}
@@ -730,7 +728,7 @@ public Object updateReactomePathways( @PathVariable(required = false) Ontology o
730728
} catch ( ReactomeException e ) {
731729
log.error( "Failed to update Reactome pathways. Could this be an issue with the ontology configuration?", e );
732730
redirectAttributes.addFlashAttribute( "message", "Failed to update Reactome pathways: " + e.getMessage() + "." );
733-
redirectAttributes.addFlashAttribute( "error", true );
731+
redirectAttributes.addFlashAttribute( "error", Boolean.TRUE );
734732
return "redirect:/admin/ontologies";
735733
}
736734
}
@@ -948,7 +946,7 @@ private Object activateOrDeactivateTerm( Ontology ontology,
948946
* Provides the ontology in OBO format.
949947
*/
950948
@GetMapping(value = "/admin/ontologies/{ontology}/download", produces = "text/plain")
951-
public ResponseEntity<StreamingResponseBody> downloadOntology( @PathVariable(required = false) Ontology ontology ) {
949+
public ResponseEntity<StreamingResponseBody> downloadOntology( @PathVariable(required = false) Ontology ontology, TimeZone timeZone ) {
952950
if ( ontology == null ) {
953951
return ResponseEntity.notFound().build();
954952
}
@@ -957,7 +955,7 @@ public ResponseEntity<StreamingResponseBody> downloadOntology( @PathVariable(req
957955
headers.set( "Content-Disposition", String.format( "attachment; filename=%s.obo", ontology.getName() ) );
958956
return new ResponseEntity<>( outputStream -> {
959957
try ( Writer writer = new OutputStreamWriter( outputStream ) ) {
960-
ontologyService.writeObo( ontology, writer );
958+
ontologyService.writeObo( ontology, writer, timeZone );
961959
}
962960
}, headers, HttpStatus.OK );
963961
}
@@ -1002,7 +1000,7 @@ public Object move( @PathVariable(required = false) Ontology ontology, @RequestP
10021000
d = OntologyService.Direction.DOWN;
10031001
} else {
10041002
return new ModelAndView( "admin/ontologies", HttpStatus.BAD_REQUEST )
1005-
.addObject( "error", true )
1003+
.addObject( "error", Boolean.TRUE )
10061004
.addObject( "message", String.format( "Invalid direction %s.", direction ) )
10071005
.addObject( "simpleOntologyForm", SimpleOntologyForm.withInitialRows() );
10081006
}

src/main/java/ubc/pavlab/rdp/controllers/SearchController.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public Object searchUsers( @Valid UserSearchParams userSearchParams, BindingResu
114114
} else {
115115
modelAndView.addObject( "Invalid user search parameters." );
116116
}
117-
modelAndView.addObject( "error", true );
117+
modelAndView.addObject( "error", Boolean.TRUE );
118118
modelAndView.addObject( "users", Collections.emptyList() );
119119
if ( userSearchParams.isISearch() ) {
120120
modelAndView.addObject( "itlUsers", Collections.emptyList() );
@@ -163,7 +163,7 @@ public ModelAndView searchUsersByName( @RequestParam String nameLike,
163163
if ( nameLike.isEmpty() ) {
164164
modelAndView.setStatus( HttpStatus.BAD_REQUEST );
165165
modelAndView.addObject( "message", "Researcher name cannot be empty." );
166-
modelAndView.addObject( "error", true );
166+
modelAndView.addObject( "error", Boolean.TRUE );
167167
modelAndView.addObject( "users", Collections.emptyList() );
168168
modelAndView.addObject( "itlUsers", Collections.emptyList() );
169169
modelAndView.addObject( "termsAvailabilityByApiUri", Collections.emptyMap() );
@@ -206,7 +206,7 @@ public ModelAndView searchUsersByDescription( @RequestParam String descriptionLi
206206
if ( descriptionLike.isEmpty() ) {
207207
modelAndView.setStatus( HttpStatus.BAD_REQUEST );
208208
modelAndView.addObject( "message", "Research interests cannot be empty." );
209-
modelAndView.addObject( "error", true );
209+
modelAndView.addObject( "error", Boolean.TRUE );
210210
modelAndView.addObject( "users", Collections.emptyList() );
211211
modelAndView.addObject( "itlUsers", Collections.emptyList() );
212212
modelAndView.addObject( "termsAvailabilityByApiUri", Collections.emptyMap() );
@@ -275,7 +275,7 @@ public ModelAndView searchUsersByGene( @RequestParam String symbol,
275275
if ( symbol.isEmpty() ) {
276276
modelAndView.setStatus( HttpStatus.BAD_REQUEST );
277277
modelAndView.addObject( "message", "Gene symbol cannot be empty." );
278-
modelAndView.addObject( "error", true );
278+
modelAndView.addObject( "error", Boolean.TRUE );
279279
return modelAndView;
280280
}
281281

src/main/java/ubc/pavlab/rdp/listeners/OntologyListener.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
import org.springframework.cache.CacheManager;
88
import org.springframework.stereotype.Component;
99
import org.springframework.transaction.event.TransactionalEventListener;
10-
import org.springframework.util.Assert;
1110
import ubc.pavlab.rdp.events.OnOntologyUpdateEvent;
1211
import ubc.pavlab.rdp.services.OntologyService;
12+
import ubc.pavlab.rdp.util.CacheUtils;
1313

1414
/**
1515
* Listener for {@link ubc.pavlab.rdp.model.ontology.Ontology}-related events.
@@ -28,10 +28,8 @@ public class OntologyListener implements InitializingBean {
2828

2929
@Override
3030
public void afterPropertiesSet() {
31-
subtreeSizeCache = cacheManager.getCache( OntologyService.SUBTREE_SIZE_BY_TERM_CACHE_NAME );
32-
Assert.notNull( subtreeSizeCache, String.format( "There is no cache named %s.", OntologyService.SIMPLE_ONTOLOGIES_CACHE_NAME ) );
33-
simpleOntologiesCache = cacheManager.getCache( OntologyService.SUBTREE_SIZE_BY_TERM_CACHE_NAME );
34-
Assert.notNull( simpleOntologiesCache, String.format( "There is no cache named %s.", OntologyService.SIMPLE_ONTOLOGIES_CACHE_NAME ) );
31+
subtreeSizeCache = CacheUtils.getCache( cacheManager, OntologyService.SUBTREE_SIZE_BY_TERM_CACHE_NAME );
32+
simpleOntologiesCache = CacheUtils.getCache( cacheManager, OntologyService.SUBTREE_SIZE_BY_TERM_CACHE_NAME );
3533
}
3634

3735
@TransactionalEventListener

src/main/java/ubc/pavlab/rdp/model/Gene.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
@Setter
2020
@EqualsAndHashCode(of = { "geneId" })
2121
@ToString(of = { "geneId", "symbol", "taxon" })
22-
public abstract class Gene {
22+
public abstract class Gene implements Serializable {
2323

2424
@NaturalId
2525
@Column(name = "gene_id")

src/main/java/ubc/pavlab/rdp/model/GeneInfo.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
@Index(columnList = "gene_id, taxon_id"),
2222
@Index(columnList = "symbol, taxon_id") })
2323
@Getter
24-
public class GeneInfo extends Gene implements Comparable<GeneInfo>, Serializable {
24+
public class GeneInfo extends Gene implements Comparable<GeneInfo> {
2525

2626
public static Comparator<GeneInfo> getComparator() {
2727
return Comparator.comparing( GeneInfo::getGeneId );

src/main/java/ubc/pavlab/rdp/model/UserGene.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
@CommonsLog
4444
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
4545
@ToString(of = { "user", "tier", "privacyLevel" }, callSuper = true)
46-
public class UserGene extends Gene implements UserContent, Serializable {
46+
public class UserGene extends Gene implements UserContent {
4747

4848
public static UserGeneBuilder builder( User user ) {
4949
return new UserGeneBuilder().user( user );

src/main/java/ubc/pavlab/rdp/model/ontology/OntologyTerm.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package ubc.pavlab.rdp.model.ontology;
22

33
import com.fasterxml.jackson.annotation.JsonIgnore;
4-
import io.micrometer.core.lang.Nullable;
54
import lombok.*;
65
import lombok.experimental.SuperBuilder;
76
import org.hibernate.annotations.NaturalId;
@@ -12,6 +11,7 @@
1211
import javax.persistence.JoinColumn;
1312
import javax.persistence.ManyToOne;
1413
import javax.persistence.MappedSuperclass;
14+
import java.io.Serializable;
1515
import java.util.Locale;
1616

1717
/**
@@ -26,7 +26,7 @@
2626
@EqualsAndHashCode(of = { "ontology", "termId" })
2727
@ToString(of = { "ontology", "termId", "name" })
2828
@SuperBuilder
29-
public abstract class OntologyTerm {
29+
public abstract class OntologyTerm implements Serializable {
3030

3131
/**
3232
* Ontology to which is term is part of.

src/main/java/ubc/pavlab/rdp/model/ontology/OntologyTermInfo.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import org.springframework.context.support.DefaultMessageSourceResolvable;
1212

1313
import javax.persistence.*;
14-
import java.io.Serializable;
1514
import java.text.Collator;
1615
import java.util.*;
1716

@@ -35,7 +34,7 @@
3534
@ToString(of = { "id" }, callSuper = true)
3635
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
3736
@SuperBuilder
38-
public class OntologyTermInfo extends OntologyTerm implements Serializable, Comparable<OntologyTermInfo> {
37+
public class OntologyTermInfo extends OntologyTerm implements Comparable<OntologyTermInfo> {
3938

4039
/**
4140
* Maximum size of term ID and name.

src/main/java/ubc/pavlab/rdp/ontology/resolvers/OlsResolver.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class OlsResolver implements OntologyResolver {
2121

2222
@Override
2323
public boolean accepts( Ontology ontology ) {
24-
return ontology.getOntologyUrl() != null && ontology.getOntologyUrl().toString().startsWith( DEFAULT_IRI_PREFIX );
24+
return ontology.getOntologyUrl() != null && ontology.getOntologyUrl().toExternalForm().startsWith( DEFAULT_IRI_PREFIX );
2525
}
2626

2727
@Override
@@ -34,6 +34,6 @@ public URI resolveViewOntologyUrl( Ontology ontology ) {
3434
public URI resolveViewTermUrl( OntologyTerm term ) {
3535
return UriComponentsBuilder.fromHttpUrl( "https://www.ebi.ac.uk/ols/ontologies/{0}/terms" )
3636
.queryParam( "iri", "{1}" )
37-
.build( term.getOntology().getName(), DEFAULT_IRI_PREFIX + term.getTermId().replace( ":", "_" ) );
37+
.build( term.getOntology().getName(), DEFAULT_IRI_PREFIX + term.getTermId().replace( ':', '_' ) );
3838
}
3939
}

src/main/java/ubc/pavlab/rdp/ontology/resolvers/OntobeeResolver.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class OntobeeResolver implements OntologyResolver {
2121

2222
@Override
2323
public boolean accepts( Ontology ontology ) {
24-
return ontology.getOntologyUrl().toString().startsWith( DEFAULT_IRI_PREFIX );
24+
return ontology.getOntologyUrl().toExternalForm().startsWith( DEFAULT_IRI_PREFIX );
2525
}
2626

2727
@Override
@@ -34,6 +34,6 @@ public URI resolveViewOntologyUrl( Ontology ontology ) {
3434
public URI resolveViewTermUrl( OntologyTerm term ) {
3535
return UriComponentsBuilder.fromHttpUrl( "https://ontobee.org/ontology/{0}" )
3636
.queryParam( "iri", "{1}" )
37-
.build( term.getOntology().getName().toUpperCase(), DEFAULT_IRI_PREFIX + term.getTermId().replace( ":", "_" ) );
37+
.build( term.getOntology().getName().toUpperCase(), DEFAULT_IRI_PREFIX + term.getTermId().replace( ':', '_' ) );
3838
}
3939
}

src/main/java/ubc/pavlab/rdp/repositories/GeneOntologyTermInfoRepository.java

+8-3
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,14 @@ public Collection<GeneOntologyTermInfo> findAllById( Iterable<String> iterable )
162162
public Stream<GeneOntologyTermInfo> findAllAsStream() {
163163
Lock lock = rwLock.readLock();
164164
lock.lock();
165-
return termsByIdOrAlias.values().stream()
166-
.onClose( lock::unlock )
167-
.distinct();
165+
try {
166+
return termsByIdOrAlias.values().stream()
167+
.onClose( lock::unlock )
168+
.distinct();
169+
} catch ( Throwable t ) {
170+
lock.unlock();
171+
throw t;
172+
}
168173
}
169174

170175
/**

src/main/java/ubc/pavlab/rdp/services/GOServiceImpl.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ public Collection<Integer> getGenesInTaxon( String id, Taxon taxon ) {
403403
}
404404
return goRepository.findById( id )
405405
.map( term -> getGenesInTaxon( term, taxon ) )
406-
.orElse( Collections.emptySet() );
406+
.orElseGet( Collections::emptySet );
407407
}
408408

409409
@Override
@@ -535,7 +535,7 @@ private void evict( Iterable<GeneOntologyTermInfo> terms ) {
535535

536536
private void evictAll() {
537537
log.debug( "Evicting all the terms from ancestors and descendants caches." );
538-
ancestorsCache.clear();
539-
descendantsCache.clear();
538+
ancestorsCache.invalidate();
539+
descendantsCache.invalidate();
540540
}
541541
}

0 commit comments

Comments
 (0)