Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,16 @@ Downloads are served by `ReportViewController` at `GET /report_view/download` wi
- DDL scripts for multiple databases in `sakai-evaluation-impl/src/ddl/`
- Database conversion scripts available for version upgrades

### DAO persistence conventions
- GenericDAO has been removed from this project. Do not add `org.sakaiproject.genericdao` dependencies, `Search`/`Restriction`/`Order` query objects, GenericDAO batch helpers, or local GenericDAO-style query helpers.
- Add new persistence behavior to the narrow domain port first (`EvaluationSettingsDao`, `EvaluationAuthoringDao`, `EvaluationAssignmentDao`, `EvaluationResponseDao`, `EvaluationQueryDao`, etc.), then implement it in the matching `EvaluationDao*Methods` slice.
- Keep query semantics readable at the call site: prefer domain method names like `getEvaluationsUsingEmailTemplate` or `deleteAssignmentsForEvaluation` over local generic query abstractions.
- Keep HQL construction and parameter binding explicit in the owning slice.
- `EvaluationDaoImpl` is only the Spring bean shell. Do not add behavior there.
- `EvaluationDaoHibernateSupport` owns the small base persistence surface still used by services and fixtures: `findById`, `findAll`, `countAll`, `create`, `save`, `update`, and `delete`.
- `SakaiComponentBeanNameAutoProxyCreator` is allowed as narrow Spring/Sakai classloader infrastructure for transactional proxies; do not expand it into DAO/query helper behavior.
- If a new transitive dependency disappears while removing persistence libraries, declare the directly used dependency explicitly rather than relying on unrelated libraries to provide it.

## Testing
Tests are located in `sakai-evaluation-impl/src/test/` and use:
- Spring Test framework for integration testing
Expand All @@ -143,4 +153,4 @@ Tests are located in `sakai-evaluation-impl/src/test/` and use:
- EntityBroker for REST API endpoints
- Spring MVC + Thymeleaf for the web UI
- Spring/Hibernate for core framework
- FreeMarker for email templating
- FreeMarker for email templating
5 changes: 0 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,6 @@
<artifactId>entitybroker-utils</artifactId>
<version>${sakai.version}</version>
</dependency>
<dependency>
<groupId>org.sakaiproject.genericdao</groupId>
<artifactId>generic-dao</artifactId>
<version>${sakai.genericdao.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

Expand Down
6 changes: 3 additions & 3 deletions sakai-evaluation-impl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,10 @@
<scope>provided</scope>
</dependency>

<!-- generic DAO -->
<dependency>
<groupId>org.sakaiproject.genericdao</groupId>
<artifactId>generic-dao</artifactId>
<groupId>org.sakaiproject</groupId>
<artifactId>reflectutils</artifactId>
<version>${reflectutils.version}</version>
</dependency>

<!-- Required for hibernate 3 HQL queries -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,36 +52,9 @@

<!-- create a DAO bean, use the hibernate implementation -->
<bean id="org.sakaiproject.evaluation.dao.EvaluationDao"
class="org.sakaiproject.evaluation.dao.EvaluationDaoImpl" init-method="init">
class="org.sakaiproject.evaluation.dao.EvaluationDaoImpl">
<property name="sessionFactory"
ref="org.sakaiproject.springframework.orm.hibernate.GlobalSessionFactory" />
<property name="persistentClasses">
<list>
<value>org.sakaiproject.evaluation.model.EvalAdhocGroup</value>
<value>org.sakaiproject.evaluation.model.EvalAdhocUser</value>
<value>org.sakaiproject.evaluation.model.EvalAdmin</value>
<value>org.sakaiproject.evaluation.model.EvalAnswer</value>
<value>org.sakaiproject.evaluation.model.EvalAssignGroup</value>
<value>org.sakaiproject.evaluation.model.EvalAssignHierarchy</value>
<value>org.sakaiproject.evaluation.model.EvalAssignUser</value>
<value>org.sakaiproject.evaluation.model.EvalConfig</value>
<value>org.sakaiproject.evaluation.model.EvalEmailProcessingData</value>
<value>org.sakaiproject.evaluation.model.EvalEmailTemplate</value>
<value>org.sakaiproject.evaluation.model.EvalEvaluation</value>
<value>org.sakaiproject.evaluation.model.EvalGroupNodes</value>
<value>org.sakaiproject.evaluation.model.EvalHierarchyRule</value>
<value>org.sakaiproject.evaluation.model.EvalItem</value>
<value>org.sakaiproject.evaluation.model.EvalItemGroup</value>
<value>org.sakaiproject.evaluation.model.EvalLock</value>
<value>org.sakaiproject.evaluation.model.EvalResponse</value>
<value>org.sakaiproject.evaluation.model.EvalScale</value>
<value>org.sakaiproject.evaluation.model.EvalTags</value>
<value>org.sakaiproject.evaluation.model.EvalTagsMeta</value>
<value>org.sakaiproject.evaluation.model.EvalTemplate</value>
<value>org.sakaiproject.evaluation.model.EvalTemplateItem</value>
<value>org.sakaiproject.evaluation.model.EvalTranslation</value>
</list>
</property>
</bean>

<!-- create a data preloading bean which will be used by the data preloader -->
Expand Down Expand Up @@ -121,7 +94,8 @@
<!-- provides the invoker access to the dao -->
<bean id="org.sakaiproject.evaluation.dao.EvalDaoInvoker"
class="org.sakaiproject.evaluation.dao.EvalDaoInvokerImpl">
<property name="dao" ref="org.sakaiproject.evaluation.dao.EvaluationDao" />
<property name="transactionManager"
ref="org.sakaiproject.springframework.orm.hibernate.GlobalTransactionManager" />
</bean>

<!-- beans for handling transactional access to all services -->
Expand All @@ -143,9 +117,13 @@
</property>
</bean>

<!-- bean to wrap DAO and all the logic beans inside the transaction interceptor -->
<!--
Legacy bean-name transaction proxying for the evaluation component.
The custom proxy creator only forces Sakai's component classloader onto
generated Spring proxies; transaction policy remains in the interceptor.
-->
<bean
class="org.sakaiproject.genericdao.springutil.CurrentClassLoaderBeanNameAutoProxyCreator">
class="org.sakaiproject.evaluation.spring.SakaiComponentBeanNameAutoProxyCreator">
<property name="interceptorNames">
<list>
<idref bean="org.sakaiproject.evaluation.interceptor.LogicTransactionProxy" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,8 @@
import org.sakaiproject.evaluation.logic.EvalSettings;
import org.sakaiproject.evaluation.model.EvalAdhocGroup;
import org.sakaiproject.evaluation.model.EvalAdhocUser;
import org.sakaiproject.genericdao.api.search.Order;
import org.sakaiproject.genericdao.api.search.Restriction;
import org.sakaiproject.genericdao.api.search.Search;

import lombok.Setter;
import lombok.extern.slf4j.Slf4j;


Expand All @@ -46,15 +44,11 @@
public class EvalAdhocSupportImpl implements EvalAdhocSupport {


@Setter
private EvaluationDao dao;
public void setDao(EvaluationDao dao) {
this.dao = dao;
}


@Setter
private EvalSettings settings;
public void setSettings(EvalSettings settings) {
this.settings = settings;
}


// USERS
Expand Down Expand Up @@ -84,10 +78,8 @@ public EvalAdhocUser getAdhocUserById(Long adhocUserId) {
public EvalAdhocUser getAdhocUserByUsername(String username) {
EvalAdhocUser user = null;
if ( (Boolean) settings.get(EvalSettings.ENABLE_ADHOC_USERS) ) {
List<EvalAdhocUser> users = dao.findBySearch(EvalAdhocUser.class,
new Search("username", username) );
if (users.size() > 0) {
user = users.get(0);
if (username != null) {
user = dao.getAdhocUserByUsername(username);
}
}
return user;
Expand All @@ -102,10 +94,8 @@ public EvalAdhocUser getAdhocUserByUsername(String username) {
public EvalAdhocUser getAdhocUserByEmail(String email) {
EvalAdhocUser user = null;
if ( (Boolean) settings.get(EvalSettings.ENABLE_ADHOC_USERS) ) {
List<EvalAdhocUser> users = dao.findBySearch(EvalAdhocUser.class,
new Search("email", email) );
if (users.size() > 0) {
user = users.get(0);
if (email != null) {
user = dao.getAdhocUserByEmail(email);
}
}
return user;
Expand Down Expand Up @@ -152,10 +142,10 @@ public List<EvalAdhocUser> getAdhocUsersByIds(Long[] ids) {
List<EvalAdhocUser> users = new ArrayList<>();
if ( (Boolean) settings.get(EvalSettings.ENABLE_ADHOC_USERS) ) {
if (ids == null) {
users = dao.findAll(EvalAdhocUser.class);
users = dao.getAllAdhocUsers();
} else {
if (ids.length > 0) {
users = dao.findBySearch(EvalAdhocUser.class, new Search("id", ids) );
users = dao.getAdhocUsersByIds(ids);
}
}
}
Expand Down Expand Up @@ -305,9 +295,9 @@ public void saveAdhocGroup(EvalAdhocGroup group) {
public List<EvalAdhocGroup> getAdhocGroupsForOwner(String userId) {
List<EvalAdhocGroup> groups = new ArrayList<>(0);
if ( (Boolean) settings.get(EvalSettings.ENABLE_ADHOC_GROUPS) ) {
groups = dao.findBySearch(EvalAdhocGroup.class, new Search(
new Restriction("owner", userId),
new Order("title") ) );
if (userId != null) {
groups = dao.getAdhocGroupsForOwner(userId);
}
}
return groups;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,23 @@
import java.util.List;

import org.sakaiproject.evaluation.model.EvalAdmin;
import org.sakaiproject.genericdao.api.search.Restriction;
import org.sakaiproject.genericdao.api.search.Search;

import lombok.Setter;

public class EvalAdminSupportImpl implements EvalAdminSupport {


@Setter
private EvaluationDao dao;
public void setDao(EvaluationDao dao) {
this.dao = dao;
}

public List<EvalAdmin> getEvalAdmins() {
return (dao.findAll(EvalAdmin.class));

public List<EvalAdmin> getEvalAdmins() {
return dao.getAllEvalAdmins();
}

public EvalAdmin getEvalAdmin(String userId) {
Search searchObj = new Search();
searchObj.addRestriction(new Restriction("userId", userId));
List<EvalAdmin> results = dao.findBySearch(EvalAdmin.class, searchObj);

if (results.isEmpty())
{
if (userId == null) {
return null;
}

return results.get(0);
return dao.getEvalAdminByUserId(userId);
}

public void assignEvalAdmin(String userId, String assignorUserId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@
*/
package org.sakaiproject.evaluation.dao;

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import lombok.Setter;

/**
* Impl
Expand All @@ -22,16 +29,26 @@
*/
public class EvalDaoInvokerImpl implements EvalDaoInvoker {

public EvaluationDao dao;
public void setDao(EvaluationDao dao) {
this.dao = dao;
}
@Setter
private PlatformTransactionManager transactionManager;

/* (non-Javadoc)
* @see org.sakaiproject.evaluation.dao.EvalDaoInvoker#invokeTransactionalAccess(java.lang.Runnable)
*/
public void invokeTransactionalAccess(Runnable toInvoke) {
dao.invokeTransactionalAccess(toInvoke);
if (transactionManager == null) {
toInvoke.run();
return;
}

TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
toInvoke.run();
}
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,13 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.sakaiproject.evaluation.constant.EvalConstants;
import org.sakaiproject.evaluation.logic.model.HierarchyNodeRule;
import org.sakaiproject.evaluation.model.EvalHierarchyRule;
import org.sakaiproject.genericdao.api.search.Restriction;
import org.sakaiproject.genericdao.api.search.Search;

import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

/**
Expand All @@ -36,11 +34,8 @@
public class EvalHierarchyRuleSupportImpl implements EvalHierarchyRuleSupport
{

@Setter
private EvaluationDao dao;
public void setDao( EvaluationDao dao )
{
this.dao = dao;
}

/*
* (non-Javadoc)
Expand Down Expand Up @@ -120,10 +115,10 @@ public void removeAllRulesForNode( Long nodeID )
log.debug( "removeAllRulesForNode( " + nodeID + " )" );
}

Set<EvalHierarchyRule> rules = new HashSet( getAllByNodeID( nodeID ) );
List<EvalHierarchyRule> rules = getAllByNodeID( nodeID );
if( !rules.isEmpty() )
{
dao.deleteSet( rules );
dao.deleteHierarchyRules( new HashSet<>( rules ) );
}
}

Expand Down Expand Up @@ -205,7 +200,7 @@ public List<HierarchyNodeRule> getAllRules()
log.debug( "getAllRules()" );
}

List<EvalHierarchyRule> rules = dao.findAll( EvalHierarchyRule.class );
List<EvalHierarchyRule> rules = dao.getAllHierarchyRules();
return convertRules( rules );
}

Expand All @@ -222,18 +217,11 @@ private EvalHierarchyRule getByID( Long ruleID )
log.debug( "getByID( " + ruleID + " )" );
}

Search searchObj = new Search();
searchObj.addRestriction( new Restriction( "id", ruleID ) );
List<EvalHierarchyRule> rules = dao.findBySearch( EvalHierarchyRule.class, searchObj );

if( rules == null || rules.isEmpty() )
if( ruleID == null )
{
return null;
}
else
{
return rules.get( 0 );
}
return dao.getHierarchyRuleById( ruleID );
}

/**
Expand All @@ -249,9 +237,11 @@ private List<EvalHierarchyRule> getAllByNodeID( Long nodeID )
log.debug( "getAllByNodeID( " + nodeID + " )" );
}

Search searchObj = new Search();
searchObj.addRestriction( new Restriction( "nodeID", nodeID ) );
List<EvalHierarchyRule> rules = dao.findBySearch( EvalHierarchyRule.class, searchObj );
if( nodeID == null )
{
return Collections.emptyList();
}
List<EvalHierarchyRule> rules = dao.getHierarchyRulesByNodeId( nodeID );
if( rules == null )
{
return Collections.emptyList();
Expand Down
Loading
Loading