Commit a878520e authored by Matija Obreza's avatar Matija Obreza

Application configuration updated and cleaned up (including tests)

- Split TemplatingConfig from MailConfig
- Moved hazelcast queues and locks from CacheConfig to HazelcastConfig
- Registered auditorAware in AuditConfig
- Split WebSecurityConfig from SecurityConfig
- Moved @EnableXXX annotations to ApplicationConfig
- Moved import of SwaggerConfig to ApplicationConfig

Tests updated
- Deleted obsolete properties files in src/test/resources
- Fixed imports
- Somehow catalog tests connected to the live database
- Removed HazelcastConfig from tests (complained about two instances with same
parent 0d2accb1
......@@ -79,7 +79,7 @@
<querydsl.version>4.1.4</querydsl.version>
<hibernate.version>4.3.11.Final</hibernate.version>
<hsqldb.version>2.3.3</hsqldb.version>
<hsqldb.version>2.3.6</hsqldb.version>
<ehcache.version>2.7.4</ehcache.version>
<slf4j.version>1.7.21</slf4j.version>
......@@ -653,12 +653,8 @@
<version>2.19.1</version>
<configuration>
<forkMode>once</forkMode>
<argLine>-Xms512m -Xmx1024m</argLine>
<argLine>-Xms512m -Xmx1024m -server</argLine>
<testFailureIgnore>false</testFailureIgnore>
<includes>
<!-- Only API documentation -->
<include>*.docs.*Test.java</include>
</includes>
</configuration>
</plugin>
<plugin>
......@@ -871,6 +867,10 @@
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>${project.build.directory}/generated-resources</directory>
<filtering>false</filtering>
......
......@@ -116,7 +116,7 @@ public class DescriptorController {
* @throws IOException
*/
@PostMapping(value = "/list")
public FilteredPage<Descriptor> listDescriptorsByFilter(@RequestParam(name = "p", required = false, defaultValue = "0") final int page,
public FilteredPage<Descriptor> listDescriptors(@RequestParam(name = "p", required = false, defaultValue = "0") final int page,
@RequestParam(name = "l", required = false, defaultValue = "50") final int pageSize,
@RequestParam(name = "d", required = false, defaultValue = "ASC") final Sort.Direction direction,
@RequestParam(name = "s", required = false, defaultValue = "id") final String[] sort,
......@@ -141,7 +141,7 @@ public class DescriptorController {
* @param filterCode the filter code
* @return the filtered page
* @throws IOException Signals that an I/O exception has occurred.
* @deprecated Use {@link #listDescriptorsByFilter(int, int, org.springframework.data.domain.Sort.Direction, String[], DescriptorFilter)}
* @deprecated Use {@link #listDescriptors(int, int, org.springframework.data.domain.Sort.Direction, String[], DescriptorFilter)}
*/
@PostMapping(value = "/list/{filterCode}")
public FilteredPage<Descriptor> listDescriptorsByShort(@RequestParam(name = "p", required = false, defaultValue = "0") final int page,
......
......@@ -43,10 +43,12 @@ import io.swagger.annotations.Api;
@Controller("adminCacheApi0")
@PreAuthorize("isAuthenticated()")
@RequestMapping(value = { "/api/v0/admin/cache", "/json/v0/cache" })
@RequestMapping(value = { CacheController.API_URL, "/json/v0/cache" })
@Api(tags = { "admin" })
public class CacheController extends ApiBaseController {
public final static String API_URL = ApiBaseController.APIv0_ADMIN_BASE + "/cache";
@Autowired
private MappingService mappingService;
......
......@@ -56,7 +56,7 @@ import net.sf.oval.Validator;
@Api(tags = { "crop" })
public class CropsController extends ApiBaseController {
protected static final String CONTROLLER_URL = ApiBaseController.APIv0_BASE + "/crops";
public static final String CONTROLLER_URL = ApiBaseController.APIv0_BASE + "/crops";
@Autowired
GenesysService genesysService;
......
......@@ -62,7 +62,7 @@ public class PermissionController extends ApiBaseController {
@RequestMapping(value = "/add", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public ApiResult addPermission(@RequestBody PermissionJson permissionJson) {
LOG.info("Adding permission {}", permissionJson);
final AclObjectIdentity oid = aclService.getObjectIdentity(permissionJson.getOid(), permissionJson.getClazz());
final AclObjectIdentity oid = aclService.ensureObjectIdentity(permissionJson.getOid(), permissionJson.getClazz());
if (permissionJson.getAuthority() != null) {
final AclSid sid = aclService.getAuthoritySid(permissionJson.getAuthority());
......
......@@ -80,7 +80,7 @@ public class AccessionId extends AuditedVersionedModel implements IdUUID {
@OneToOne(fetch = FetchType.LAZY, cascade = { CascadeType.ALL }, optional = true, orphanRemoval = true)
@JoinColumn(name = "pdciId", unique = true)
@JsonIgnoreProperties({ "accession" })
@JsonView({ JsonViews.Root.class })
@JsonView({ JsonViews.Internal.class })
private PDCI pdci;
@Column(name = "storage", nullable = false)
......
......@@ -49,7 +49,7 @@ public class AccessionListServiceImpl implements AccessionListService {
@Autowired
AccessionListRepository accessionListRepository;
@Autowired
@Autowired(required = false)
ElasticUpdater elasticUpdater;
@Override
......@@ -95,9 +95,10 @@ public class AccessionListServiceImpl implements AccessionListService {
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#accessionList, 'WRITE')")
@Transactional
public void removeAll(AccessionList accessionList) {
// Re-index
elasticUpdater.updateAll(Accession.class, accessionListRepository.getAccessionIds(accessionList).toArray(ArrayUtils.EMPTY_LONG_OBJECT_ARRAY));
if (elasticUpdater!=null) {
// Re-index
elasticUpdater.updateAll(Accession.class, accessionListRepository.getAccessionIds(accessionList).toArray(ArrayUtils.EMPTY_LONG_OBJECT_ARRAY));
}
accessionListRepository.removeAll(accessionList);
}
......@@ -105,9 +106,10 @@ public class AccessionListServiceImpl implements AccessionListService {
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#accessionList, 'WRITE')")
@Transactional
public void addToList(AccessionList list, AccessionData accession) {
// Re-index
elasticUpdater.update(Accession.class, accession.getId());
if (elasticUpdater!=null) {
// Re-index
elasticUpdater.update(Accession.class, accession.getId());
}
accessionListRepository.addOne(list, accession.getAccessionId());
}
......@@ -120,22 +122,28 @@ public class AccessionListServiceImpl implements AccessionListService {
accessionListRepository.addAll(acceList, accessionIds);
// Re-index
elasticUpdater.updateAll(Accession.class, accessionIds.toArray(ArrayUtils.EMPTY_LONG_OBJECT_ARRAY));
if (elasticUpdater!=null) {
// Re-index
elasticUpdater.updateAll(Accession.class, accessionIds.toArray(ArrayUtils.EMPTY_LONG_OBJECT_ARRAY));
}
}
@Override
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#accessionList, 'WRITE')")
@Transactional
public void setList(AccessionList accessionList, Collection<Long> accessionIds) {
// Re-index
elasticUpdater.updateAll(Accession.class, accessionListRepository.getAccessionIds(accessionList).toArray(ArrayUtils.EMPTY_LONG_OBJECT_ARRAY));
if (elasticUpdater!=null) {
// Re-index
elasticUpdater.updateAll(Accession.class, accessionListRepository.getAccessionIds(accessionList).toArray(ArrayUtils.EMPTY_LONG_OBJECT_ARRAY));
}
accessionListRepository.removeAll(accessionList);
accessionListRepository.addAll(accessionList, accessionIds);
// Re-index
elasticUpdater.updateAll(Accession.class, accessionIds.toArray(ArrayUtils.EMPTY_LONG_OBJECT_ARRAY));
if (elasticUpdater!=null) {
// Re-index
elasticUpdater.updateAll(Accession.class, accessionIds.toArray(ArrayUtils.EMPTY_LONG_OBJECT_ARRAY));
}
}
@Override
......@@ -144,17 +152,20 @@ public class AccessionListServiceImpl implements AccessionListService {
public void addToList(AccessionList accessionList, AppliedFilters filters) {
accessionListRepository.addAll(accessionList, filters);
// Re-index
elasticUpdater.updateAll(Accession.class, accessionListRepository.getAccessionIds(accessionList).toArray(ArrayUtils.EMPTY_LONG_OBJECT_ARRAY));
if (elasticUpdater!=null) {
// Re-index
elasticUpdater.updateAll(Accession.class, accessionListRepository.getAccessionIds(accessionList).toArray(ArrayUtils.EMPTY_LONG_OBJECT_ARRAY));
}
}
@Override
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#accessionList, 'DELETE')")
@Transactional
public void delete(AccessionList accessionList) {
// Re-index
elasticUpdater.updateAll(Accession.class, accessionListRepository.getAccessionIds(accessionList).toArray(ArrayUtils.EMPTY_LONG_OBJECT_ARRAY));
if (elasticUpdater!=null) {
// Re-index
elasticUpdater.updateAll(Accession.class, accessionListRepository.getAccessionIds(accessionList).toArray(ArrayUtils.EMPTY_LONG_OBJECT_ARRAY));
}
accessionListRepository.delete(accessionList);
}
......
......@@ -25,6 +25,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import javax.annotation.Resource;
......@@ -58,8 +59,6 @@ import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import com.hazelcast.core.ILock;
@Service
public class ElasticSearchManagementServiceImpl implements ElasticSearchManagementService {
......@@ -81,7 +80,7 @@ public class ElasticSearchManagementServiceImpl implements ElasticSearchManageme
private GenesysLowlevelRepository genesysLowlevelRepository;
@Resource
private ILock elasticsearchAdminLock;
private Lock elasticsearchAdminLock;
private final Map<String, Class<?>> clazzMap;
......
......@@ -15,10 +15,7 @@
**/
package org.genesys2.server.service.impl;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.functionScoreQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
import static org.elasticsearch.index.query.QueryBuilders.queryStringQuery;
import static org.elasticsearch.index.query.QueryBuilders.*;
import static org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders.fieldValueFactorFunction;
import java.util.ArrayList;
......@@ -35,7 +32,6 @@ import org.genesys2.server.model.impl.ActivityPost;
import org.genesys2.server.model.impl.Article;
import org.genesys2.server.model.impl.Country;
import org.genesys2.server.model.impl.FaoInstitute;
import org.genesys2.server.mvc.JspHelper;
import org.genesys2.server.persistence.ActivityPostRepository;
import org.genesys2.server.persistence.ArticleRepository;
import org.genesys2.server.persistence.CountryRepository;
......@@ -86,9 +82,6 @@ public class FullTextSearchServiceImpl implements FullTextSearchService, Initial
@Autowired
private FaoInstituteRepository instituteRepository;
@Autowired
private JspHelper jspHelper;
@Autowired
private ContentService contentService;
......@@ -326,7 +319,7 @@ public class FullTextSearchServiceImpl implements FullTextSearchService, Initial
document.setSummary(activityPost.getTitle());
document.setCreatedDate(activityPost.getCreatedDate());
document.setLastModifiedDate(activityPost.getLastModifiedDate());
document.setUrlToContent("/content/news/" + activityPost.getId() + "/" + this.jspHelper.suggestUrlForText(activityPost.getTitle()));
document.setUrlToContent("/content/news/" + activityPost.getId() + "/");
}
private void updateDocument(Country country, FullTextDocument document) {
......
......@@ -14,7 +14,7 @@
* limitations under the License.
**/
package org.genesys2.server.persistence;
package org.genesys2.server.service.impl;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
......@@ -24,7 +24,8 @@ import java.sql.SQLException;
import java.util.List;
import org.genesys2.server.model.genesys.Method;
import org.genesys2.server.service.impl.DirectMysqlQuery;
import org.genesys2.server.persistence.GenesysLowlevelRepository;
import org.genesys2.server.persistence.MethodRepository;
import org.genesys2.server.service.impl.DirectMysqlQuery.MethodResolver;
import org.genesys2.server.service.impl.FilterHandler.AppliedFilters;
import org.slf4j.Logger;
......
......@@ -17,6 +17,7 @@
package org.genesys2.server.service.impl;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import javax.annotation.Resource;
......@@ -49,7 +50,7 @@ public class TaxonomyManager {
* update logic
*/
@Resource
private ILock taxonomyUpdateLock;
private Lock taxonomyUpdateLock;
public Taxonomy2 ensureTaxonomy2(String genus, String species, String spAuthor, String subtaxa, String subtAuthor) {
if (StringUtils.isBlank(genus)) {
......
......@@ -14,7 +14,7 @@
* limitations under the License.
**/
package org.genesys2.server.persistence;
package org.genesys2.server.service.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
......@@ -37,6 +37,11 @@ import org.genesys2.server.model.genesys.ExperimentAccessionTrait;
import org.genesys2.server.model.genesys.ExperimentTrait;
import org.genesys2.server.model.genesys.Metadata;
import org.genesys2.server.model.genesys.Method;
import org.genesys2.server.persistence.AccessionTraitRepository;
import org.genesys2.server.persistence.MetadataAccessionRepository;
import org.genesys2.server.persistence.MetadataMethodRepository;
import org.genesys2.server.persistence.MethodRepository;
import org.genesys2.server.persistence.TraitValueRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -51,7 +56,7 @@ import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
@Repository
@Transactional(readOnly = true)
//@Transactional(readOnly = true)
public class TraitValueRepositoryImpl implements TraitValueRepository {
public static final Logger LOG = LoggerFactory.getLogger(TraitValueRepository.class);
private JdbcTemplate jdbcTemplate;
......
......@@ -22,6 +22,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import javax.annotation.Resource;
......@@ -34,8 +35,6 @@ import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.stereotype.Component;
import com.hazelcast.core.IQueue;
/**
* Component that receives updated or deleted accession IDs and uses a
* background thread to refresh ES
......@@ -50,10 +49,10 @@ public class ElasticUpdater {
private ElasticsearchTemplate elasticsearchTemplate;
@Resource
private IQueue<ElasticNode> elasticRemoveQueue;
private BlockingQueue<ElasticNode> elasticRemoveQueue;
@Resource
private IQueue<ElasticNode> elasticUpdateQueue;
private BlockingQueue<ElasticNode> elasticUpdateQueue;
/**
* Schedule objects for removal
......
......@@ -337,7 +337,10 @@ public class ElasticUpdaterAspect {
if (LOG.isTraceEnabled()) {
LOG.trace("Returning from {} id={}", joinPoint.toLongString(), (long) joinPoint.getArgs()[0]);
}
elasticUpdater.remove(Article.class, (Long) joinPoint.getArgs()[0]);
// test for deleteAll with no args
if (joinPoint.getArgs().length > 0) {
elasticUpdater.remove(Article.class, (Long) joinPoint.getArgs()[0]);
}
}
/**
......@@ -352,7 +355,10 @@ public class ElasticUpdaterAspect {
if (LOG.isTraceEnabled()) {
LOG.trace("Returning from {} id={}", joinPoint.toLongString(), (long) joinPoint.getArgs()[0]);
}
elasticUpdater.remove(FullTextDocument.class, (Long) joinPoint.getArgs()[0]);
// test for deleteAll with no args
if (joinPoint.getArgs().length > 0) {
elasticUpdater.remove(FullTextDocument.class, (Long) joinPoint.getArgs()[0]);
}
}
/**
......@@ -367,7 +373,10 @@ public class ElasticUpdaterAspect {
if (LOG.isTraceEnabled()) {
LOG.trace("Returning from {} id={}", joinPoint.toLongString(), (long) joinPoint.getArgs()[0]);
}
elasticUpdater.remove(Country.class, (Long) joinPoint.getArgs()[0]);
// test for deleteAll with no args
if (joinPoint.getArgs().length > 0) {
elasticUpdater.remove(Country.class, (Long) joinPoint.getArgs()[0]);
}
}
/**
......@@ -382,6 +391,9 @@ public class ElasticUpdaterAspect {
if (LOG.isTraceEnabled()) {
LOG.trace("Returning from {} id={}", joinPoint.toLongString(), (long) joinPoint.getArgs()[0]);
}
elasticUpdater.remove(FaoInstitute.class, (Long) joinPoint.getArgs()[0]);
// test for deleteAll with no args
if (joinPoint.getArgs().length > 0) {
elasticUpdater.remove(FaoInstitute.class, (Long) joinPoint.getArgs()[0]);
}
}
}
......@@ -3,6 +3,7 @@ package org.genesys2.server.service.worker;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import javax.annotation.Resource;
......@@ -17,14 +18,12 @@ import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import com.hazelcast.core.IQueue;
/**
* ES Processor component uses Spring's @Scheduled annotation to scan queues with 2000ms delay measured from the
* completion time of each preceding invocation.
*/
@Component
class ElasticUpdaterProcessor {
public class ElasticUpdaterProcessor {
public static final Logger LOG = LoggerFactory.getLogger(ElasticUpdaterProcessor.class);
private static final int BATCH_SIZE = 100;
......@@ -39,10 +38,10 @@ class ElasticUpdaterProcessor {
private ThreadPoolTaskExecutor executor;
@Resource
private IQueue<ElasticNode> elasticRemoveQueue;
private BlockingQueue<ElasticNode> elasticRemoveQueue;
@Resource
private IQueue<ElasticNode> elasticUpdateQueue;
private BlockingQueue<ElasticNode> elasticUpdateQueue;
private HashMap<String, Set<Long>> buckets = new HashMap<String, Set<Long>>();
......
......@@ -33,16 +33,23 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@Configuration
@Import({ CommonConfig.class, SchedulerConfig.class, DatabaseConfig.class, MailConfig.class, OAuth2ServerConfig.class, SecurityConfig.class, CacheConfig.class,
ElasticsearchConfig.class, FileRepositoryConfig.class, WebConfiguration.class, AuditConfig.class, GLISConfig.class })
@Import({ HazelcastConfig.class, CommonConfig.class, SchedulerConfig.class, DatabaseConfig.class, TemplatingConfig.class, MailConfig.class, OAuth2ServerConfig.class, SecurityConfig.class, CacheConfig.class,
ElasticsearchConfig.class, FileRepositoryConfig.class, WebSecurityConfig.class, WebConfiguration.class, AuditConfig.class, GLISConfig.class, SwaggerConfig.class })
@EnableAspectJAutoProxy
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class ApplicationConfig {
public static final Logger LOG = LoggerFactory.getLogger(ApplicationConfig.class);
......
......@@ -20,8 +20,10 @@ import org.genesys.blocks.auditlog.service.AuditTrailService;
import org.genesys.blocks.auditlog.service.ClassPKService;
import org.genesys.blocks.auditlog.service.impl.AuditTrailServiceImpl;
import org.genesys.blocks.auditlog.service.impl.ClassPKServiceImpl;
import org.genesys.blocks.security.SpringSecurityAuditorAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.AuditorAware;
/**
* Configuration of audit-related components and services.
......@@ -30,6 +32,11 @@ import org.springframework.context.annotation.Configuration;
*/
@Configuration
public class AuditConfig {
@Bean
public AuditorAware<?> auditorAware() {
return new SpringSecurityAuditorAware();
}
@Bean
public ClassPKService classPkService() {
......
......@@ -16,152 +16,16 @@
package org.genesys2.spring.config;
import java.util.Properties;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IExecutorService;
import com.hazelcast.core.IMap;
import com.hazelcast.core.IQueue;
import com.hazelcast.spring.cache.HazelcastCacheManager;
import com.hazelcast.web.WebFilter;
import com.hazelcast.web.spring.SpringAwareWebFilter;
import org.genesys.blocks.security.lockout.AccountLockoutManager.AttemptStatistics;
import org.genesys.catalog.service.impl.ShortFilterServiceImpl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
@Configuration
@EnableCaching
@Import({ HazelcastConfig.class })
public class CacheConfig {
/** The instance name. */
@Value("${hazelcast.instanceName}")
protected String instanceName = "genesys";
@Value("${base.cookie-domain}")
private String cookieDomain;
@Value("${base.cookie-secure}")
private String cookieSecure;
@Value("${base.cookie-http-only}")
private String cookieHttpOnly;
/**
* Cache manager.
*
* @param hazelcastInstance the hazelcast instance
* @return the hazelcast cache manager
*/
@Bean
public HazelcastCacheManager cacheManager(final HazelcastInstance hazelcastInstance) {
final HazelcastCacheManager cm = new HazelcastCacheManager(hazelcastInstance);
return cm;
}
/**
* Tileserver map.
*
* @param hazelcast the hazelcast
* @return the i map
*/
@Bean
public IMap<Object, Object> tileserverMap(final HazelcastInstance hazelcast) {
final IMap<Object, Object> x = hazelcast.getMap("tileserver");
return x;
}
/**