diff --git a/inception/inception-annotation-storage/src/main/java/de/tudarmstadt/ukp/inception/annotation/storage/CasStorageServiceImpl.java b/inception/inception-annotation-storage/src/main/java/de/tudarmstadt/ukp/inception/annotation/storage/CasStorageServiceImpl.java index 9099169c90f..cd6a313fe4c 100644 --- a/inception/inception-annotation-storage/src/main/java/de/tudarmstadt/ukp/inception/annotation/storage/CasStorageServiceImpl.java +++ b/inception/inception-annotation-storage/src/main/java/de/tudarmstadt/ukp/inception/annotation/storage/CasStorageServiceImpl.java @@ -58,7 +58,6 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataRetrievalFailureException; -import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.event.TransactionalEventListener; import org.springframework.util.ConcurrentReferenceHashMap; @@ -1064,7 +1063,6 @@ private void logExclusiveAccessHolders() } @TransactionalEventListener(fallbackExecution = true) - @Transactional public void beforeLayerConfigurationChanged(LayerConfigurationChangedEvent aEvent) { // Tell the known CAS holders for the given project that their type system is outdated diff --git a/inception/inception-external-editor/src/main/java/de/tudarmstadt/ukp/inception/externaleditor/config/ExternalEditorLoader.java b/inception/inception-external-editor/src/main/java/de/tudarmstadt/ukp/inception/externaleditor/config/ExternalEditorLoader.java index 6666384fc32..d80c281f756 100644 --- a/inception/inception-external-editor/src/main/java/de/tudarmstadt/ukp/inception/externaleditor/config/ExternalEditorLoader.java +++ b/inception/inception-external-editor/src/main/java/de/tudarmstadt/ukp/inception/externaleditor/config/ExternalEditorLoader.java @@ -49,7 +49,7 @@ import de.tudarmstadt.ukp.inception.support.SettingsUtil; @ConditionalOnWebApplication -@Configuration +@Configuration(proxyBeanMethods = false) public class ExternalEditorLoader implements BeanDefinitionRegistryPostProcessor, WebMvcConfigurer { diff --git a/inception/inception-io-xml/src/main/java/de/tudarmstadt/ukp/inception/io/xml/CustomXmlFormatLoader.java b/inception/inception-io-xml/src/main/java/de/tudarmstadt/ukp/inception/io/xml/CustomXmlFormatLoader.java index d695127c07c..fd456a0bb38 100644 --- a/inception/inception-io-xml/src/main/java/de/tudarmstadt/ukp/inception/io/xml/CustomXmlFormatLoader.java +++ b/inception/inception-io-xml/src/main/java/de/tudarmstadt/ukp/inception/io/xml/CustomXmlFormatLoader.java @@ -44,7 +44,7 @@ import de.tudarmstadt.ukp.inception.support.SettingsUtil; @ConditionalOnProperty(prefix = "format.custom-xml", name = "enabled", havingValue = "true", matchIfMissing = false) -@Configuration +@Configuration(proxyBeanMethods = false) public class CustomXmlFormatLoader implements BeanDefinitionRegistryPostProcessor { diff --git a/inception/inception-kb/src/main/java/de/tudarmstadt/ukp/inception/kb/model/KnowledgeBase.java b/inception/inception-kb/src/main/java/de/tudarmstadt/ukp/inception/kb/model/KnowledgeBase.java index 515c9429727..96a8f9646f7 100644 --- a/inception/inception-kb/src/main/java/de/tudarmstadt/ukp/inception/kb/model/KnowledgeBase.java +++ b/inception/inception-kb/src/main/java/de/tudarmstadt/ukp/inception/kb/model/KnowledgeBase.java @@ -35,13 +35,13 @@ import de.tudarmstadt.ukp.inception.kb.IriConstants; import de.tudarmstadt.ukp.inception.kb.RepositoryType; import de.tudarmstadt.ukp.inception.kb.reification.Reification; +import de.tudarmstadt.ukp.inception.kb.reification.ReificationType; import de.tudarmstadt.ukp.inception.kb.yaml.KnowledgeBaseMapping; import de.tudarmstadt.ukp.inception.kb.yaml.KnowledgeBaseProfile; import jakarta.persistence.CollectionTable; import jakarta.persistence.Column; import jakarta.persistence.ElementCollection; import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; import jakarta.persistence.FetchType; import jakarta.persistence.Id; @@ -176,7 +176,7 @@ public class KnowledgeBase private boolean enabled = true; @Column(nullable = false) - @Enumerated(EnumType.STRING) + @Type(ReificationType.class) private Reification reification = NONE; /** diff --git a/inception/inception-kb/src/main/java/de/tudarmstadt/ukp/inception/kb/reification/Reification.java b/inception/inception-kb/src/main/java/de/tudarmstadt/ukp/inception/kb/reification/Reification.java index 033d70c00cd..1822fc61f85 100644 --- a/inception/inception-kb/src/main/java/de/tudarmstadt/ukp/inception/kb/reification/Reification.java +++ b/inception/inception-kb/src/main/java/de/tudarmstadt/ukp/inception/kb/reification/Reification.java @@ -17,14 +17,20 @@ */ package de.tudarmstadt.ukp.inception.kb.reification; +import de.tudarmstadt.ukp.inception.support.db.PersistentEnum; + public enum Reification + implements PersistentEnum { - NONE(false), WIKIDATA(true); + NONE("NONE", false), WIKIDATA("WIKIDATA", true); private final boolean supportsQualifier; - Reification(boolean supportsQualifier) + private final String id; + + Reification(String aId, boolean supportsQualifier) { + this.id = aId; this.supportsQualifier = supportsQualifier; } @@ -32,4 +38,21 @@ public boolean supportsQualifier() { return supportsQualifier; } + + @Override + public String getId() + { + return id; + } + + public String getName() + { + return getId(); + } + + @Override + public String toString() + { + return getId(); + } } diff --git a/inception/inception-kb/src/main/java/de/tudarmstadt/ukp/inception/kb/reification/ReificationType.java b/inception/inception-kb/src/main/java/de/tudarmstadt/ukp/inception/kb/reification/ReificationType.java new file mode 100644 index 00000000000..2b383e25d3e --- /dev/null +++ b/inception/inception-kb/src/main/java/de/tudarmstadt/ukp/inception/kb/reification/ReificationType.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Technische Universität Darmstadt under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The Technische Universität Darmstadt + * licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.tudarmstadt.ukp.inception.kb.reification; + +import de.tudarmstadt.ukp.inception.support.db.PersistentEnumUserType; + +/** + * Implementation of {@link PersistentEnumUserType} + * + */ +public class ReificationType + extends PersistentEnumUserType +{ + private static final long serialVersionUID = -5458676818846846515L; + + @Override + public Class returnedClass() + { + return Reification.class; + } +} diff --git a/inception/inception-recommendation-api/src/main/java/de/tudarmstadt/ukp/inception/recommendation/api/model/Recommender.java b/inception/inception-recommendation-api/src/main/java/de/tudarmstadt/ukp/inception/recommendation/api/model/Recommender.java index 7186cfdeeed..59fed98311e 100644 --- a/inception/inception-recommendation-api/src/main/java/de/tudarmstadt/ukp/inception/recommendation/api/model/Recommender.java +++ b/inception/inception-recommendation-api/src/main/java/de/tudarmstadt/ukp/inception/recommendation/api/model/Recommender.java @@ -24,8 +24,10 @@ import org.hibernate.annotations.OnDelete; import org.hibernate.annotations.OnDeleteAction; +import org.hibernate.annotations.Type; import de.tudarmstadt.ukp.clarin.webanno.model.AnnotationDocumentState; +import de.tudarmstadt.ukp.clarin.webanno.model.AnnotationDocumentStateType; import de.tudarmstadt.ukp.clarin.webanno.model.AnnotationFeature; import de.tudarmstadt.ukp.clarin.webanno.model.AnnotationLayer; import de.tudarmstadt.ukp.clarin.webanno.model.Project; @@ -33,8 +35,6 @@ import jakarta.persistence.Column; import jakarta.persistence.ElementCollection; import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -93,7 +93,7 @@ public class Recommender @ElementCollection(fetch = FetchType.EAGER) @CollectionTable(name = "recommender_ignored_document_states") @Column(name = "name", nullable = false) - @Enumerated(EnumType.STRING) + @Type(AnnotationDocumentStateType.class) private Set statesIgnoredForTraining; @Lob diff --git a/inception/inception-remote/src/main/java/de/tudarmstadt/ukp/clarin/webanno/webapp/remoteapi/webhooks/WebhookService.java b/inception/inception-remote/src/main/java/de/tudarmstadt/ukp/clarin/webanno/webapp/remoteapi/webhooks/WebhookService.java index 4c8070985b8..d710b1bf489 100644 --- a/inception/inception-remote/src/main/java/de/tudarmstadt/ukp/clarin/webanno/webapp/remoteapi/webhooks/WebhookService.java +++ b/inception/inception-remote/src/main/java/de/tudarmstadt/ukp/clarin/webanno/webapp/remoteapi/webhooks/WebhookService.java @@ -150,7 +150,7 @@ public void init() @Async public void onApplicationEvent(ApplicationEvent aEvent) { - String topic = EVENT_TOPICS.get(aEvent.getClass()); + var topic = EVENT_TOPICS.get(aEvent.getClass()); if (topic == null) { return; } diff --git a/inception/inception-search-core/src/main/java/de/tudarmstadt/ukp/inception/search/SearchServiceImpl.java b/inception/inception-search-core/src/main/java/de/tudarmstadt/ukp/inception/search/SearchServiceImpl.java index b841d93bf87..8e83fa64b6b 100644 --- a/inception/inception-search-core/src/main/java/de/tudarmstadt/ukp/inception/search/SearchServiceImpl.java +++ b/inception/inception-search-core/src/main/java/de/tudarmstadt/ukp/inception/search/SearchServiceImpl.java @@ -26,6 +26,7 @@ import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toUnmodifiableSet; +import static org.springframework.transaction.annotation.Propagation.REQUIRES_NEW; import java.io.FileNotFoundException; import java.io.IOException; @@ -403,7 +404,6 @@ public void beforeDocumentRemove(BeforeDocumentRemovedEvent aEvent) throws IOExc } @TransactionalEventListener(fallbackExecution = true) - @Transactional public void afterDocumentCreate(AfterDocumentCreatedEvent aEvent) { log.trace("Starting afterDocumentCreate"); @@ -413,7 +413,6 @@ public void afterDocumentCreate(AfterDocumentCreatedEvent aEvent) } @TransactionalEventListener(fallbackExecution = true) - @Transactional public void afterAnnotationUpdate(AfterCasWrittenEvent aEvent) { log.trace("Starting afterAnnotationUpdate"); @@ -423,12 +422,12 @@ public void afterAnnotationUpdate(AfterCasWrittenEvent aEvent) } @TransactionalEventListener(fallbackExecution = true) - @Transactional + @Transactional(propagation = REQUIRES_NEW) public void beforeLayerConfigurationChanged(LayerConfigurationChangedEvent aEvent) { log.trace("Starting beforeLayerConfigurationChanged"); - Project project = aEvent.getProject(); + var project = aEvent.getProject(); try (PooledIndex pooledIndex = acquireIndex(project.getId())) { pooledIndex.forceRecycle(); diff --git a/inception/inception-security/src/main/java/de/tudarmstadt/ukp/clarin/webanno/security/SuccessfulLoginListener.java b/inception/inception-security/src/main/java/de/tudarmstadt/ukp/clarin/webanno/security/SuccessfulLoginListener.java index 67d2f290f61..2674eafe184 100644 --- a/inception/inception-security/src/main/java/de/tudarmstadt/ukp/clarin/webanno/security/SuccessfulLoginListener.java +++ b/inception/inception-security/src/main/java/de/tudarmstadt/ukp/clarin/webanno/security/SuccessfulLoginListener.java @@ -19,30 +19,32 @@ import java.util.Date; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.security.authentication.event.AuthenticationSuccessEvent; -import org.springframework.stereotype.Component; -import de.tudarmstadt.ukp.clarin.webanno.security.model.User; +import de.tudarmstadt.ukp.clarin.webanno.security.config.SecurityAutoConfiguration; -@Component(SuccessfulLoginListener.SERVICE_NAME) +/** + *

+ * This class is exposed as a Spring Component via + * {@link SecurityAutoConfiguration#successfulLoginListener}. + *

+ */ public class SuccessfulLoginListener - implements ApplicationListener + implements ApplicationListener { - public static final String SERVICE_NAME = "successfulLoginListener"; + private final UserDao userRepository; - private @Autowired UserDao userRepository; + public SuccessfulLoginListener(UserDao aUserRepository) + { + userRepository = aUserRepository; + } @Override - public void onApplicationEvent(ApplicationEvent aEvent) + public void onApplicationEvent(AuthenticationSuccessEvent aEvent) { - if (aEvent instanceof AuthenticationSuccessEvent) { - AuthenticationSuccessEvent event = (AuthenticationSuccessEvent) aEvent; - User user = userRepository.get(event.getAuthentication().getName()); - user.setLastLogin(new Date(event.getTimestamp())); - userRepository.update(user); - } + var user = userRepository.get(aEvent.getAuthentication().getName()); + user.setLastLogin(new Date(aEvent.getTimestamp())); + userRepository.update(user); } } diff --git a/inception/inception-security/src/main/java/de/tudarmstadt/ukp/clarin/webanno/security/config/SecurityAutoConfiguration.java b/inception/inception-security/src/main/java/de/tudarmstadt/ukp/clarin/webanno/security/config/SecurityAutoConfiguration.java index 94adfdd3983..6900bcd3485 100644 --- a/inception/inception-security/src/main/java/de/tudarmstadt/ukp/clarin/webanno/security/config/SecurityAutoConfiguration.java +++ b/inception/inception-security/src/main/java/de/tudarmstadt/ukp/clarin/webanno/security/config/SecurityAutoConfiguration.java @@ -19,7 +19,6 @@ import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; @@ -45,6 +44,7 @@ import de.tudarmstadt.ukp.clarin.webanno.security.PermissionExtension; import de.tudarmstadt.ukp.clarin.webanno.security.PermissionExtensionPoint; import de.tudarmstadt.ukp.clarin.webanno.security.PermissionExtensionPointImpl; +import de.tudarmstadt.ukp.clarin.webanno.security.SuccessfulLoginListener; import de.tudarmstadt.ukp.clarin.webanno.security.UserAccess; import de.tudarmstadt.ukp.clarin.webanno.security.UserAccessImpl; import de.tudarmstadt.ukp.clarin.webanno.security.UserDao; @@ -87,11 +87,10 @@ public PasswordEncoder passwordEncoder() { // Set up a DelegatingPasswordEncoder which decodes legacy passwords using the // StandardPasswordEncoder but encodes passwords using the modern BCryptPasswordEncoder - String encoderForEncoding = "bcrypt"; - Map encoders = new HashMap<>(); + var encoderForEncoding = "bcrypt"; + var encoders = new HashMap(); encoders.put(encoderForEncoding, new BCryptPasswordEncoder()); - DelegatingPasswordEncoder delegatingEncoder = new DelegatingPasswordEncoder( - encoderForEncoding, encoders); + var delegatingEncoder = new DelegatingPasswordEncoder(encoderForEncoding, encoders); // Decode legacy passwords without encoder ID using the StandardPasswordEncoder delegatingEncoder.setDefaultPasswordEncoderForMatches(new StandardPasswordEncoder()); return delegatingEncoder; @@ -115,7 +114,7 @@ public ExtensiblePermissionEvaluator extensiblePermissionEvaluator( public MethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler( ApplicationContext aContext, ExtensiblePermissionEvaluator aEvaluator) { - DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); + var expressionHandler = new DefaultMethodSecurityExpressionHandler(); expressionHandler.setApplicationContext(aContext); expressionHandler.setPermissionEvaluator(aEvaluator); return expressionHandler; @@ -144,4 +143,10 @@ public UserAccess userAccess(UserDao aUserService) { return new UserAccessImpl(aUserService); } + + @Bean + public SuccessfulLoginListener successfulLoginListener(UserDao aUserRepository) + { + return new SuccessfulLoginListener(aUserRepository); + } }