From 942765093b92dedb6d37b26a5c84dc346d2fcab4 Mon Sep 17 00:00:00 2001 From: robokaso Date: Mon, 18 Feb 2008 13:45:02 +0000 Subject: [PATCH] IN PROGRESS - issue BATCH-340: Refactor JobRepository for greater clarity and consistency. http://jira.springframework.org/browse/BATCH-340 cleaned up method signatures in dao interfaces to uniformly use domain object arguments (rather than ids sometimes) --- .../repository/SimpleJobRepository.java | 8 +++--- .../repository/dao/JdbcJobExecutionDao.java | 4 +-- .../repository/dao/JdbcStepExecutionDao.java | 11 +++++--- .../repository/dao/JobExecutionDao.java | 6 ++--- .../execution/repository/dao/MapJobDao.java | 4 +-- .../execution/repository/dao/MapStepDao.java | 8 +++--- .../repository/dao/StepExecutionDao.java | 6 ++--- .../execution/repository/MockStepDao.java | 8 +++--- .../repository/SimpleJobRepositoryTests.java | 26 +++++++++---------- .../repository/dao/AbstractJobDaoTests.java | 6 ++--- .../repository/dao/AbstractStepDaoTests.java | 18 ++++++------- .../repository/dao/MapJobDaoTests.java | 6 ++--- 12 files changed, 55 insertions(+), 56 deletions(-) diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/SimpleJobRepository.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/SimpleJobRepository.java index e2b7ea686..d1807b7a6 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/SimpleJobRepository.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/SimpleJobRepository.java @@ -171,7 +171,7 @@ public class SimpleJobRepository implements JobRepository { if (jobs.size() == 1) { // One job was found jobInstance = (JobInstance) jobs.get(0); - jobInstance.setJobExecutionCount(jobExecutionDao.getJobExecutionCount(jobInstance.getId())); + jobInstance.setJobExecutionCount(jobExecutionDao.getJobExecutionCount(jobInstance)); if (jobInstance.getJobExecutionCount() > job.getStartLimit()) { throw new BatchRestartException("Restart Max exceeded for Job: " + jobInstance.toString()); } @@ -264,12 +264,12 @@ public class SimpleJobRepository implements JobRepository { jobExecutionDao.saveJobExecution(jobExecution); } stepExecutionDao.saveStepExecution(stepExecution); - stepExecutionDao.saveExecutionContext(stepExecution.getId(), stepExecution.getExecutionContext()); + stepExecutionDao.saveExecutionContext(stepExecution); } else { // existing execution, update stepExecutionDao.updateStepExecution(stepExecution); - stepExecutionDao.updateExecutionContext(stepExecution.getId(), stepExecution.getExecutionContext()); + stepExecutionDao.updateExecutionContext(stepExecution); } } @@ -316,7 +316,7 @@ public class SimpleJobRepository implements JobRepository { stepInstance.setLastExecution(stepExecutionDao.getLastStepExecution(stepInstance, lastJobExecution)); if (stepInstance.getLastExecution() != null) { ExecutionContext executionContext = stepExecutionDao.findExecutionContext(stepInstance - .getLastExecution().getId()); + .getLastExecution()); stepInstance.getLastExecution().setExecutionContext(executionContext); } stepInstance.setStepExecutionCount(stepExecutionDao.getStepExecutionCount(stepInstance)); diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcJobExecutionDao.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcJobExecutionDao.java index b34189bd5..ded693f9b 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcJobExecutionDao.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcJobExecutionDao.java @@ -65,8 +65,8 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements * @see JobDao#getJobExecutionCount(JobInstance) * @throws IllegalArgumentException if jobId is null. */ - public int getJobExecutionCount(Long jobId) { - + public int getJobExecutionCount(JobInstance jobInstance) { + Long jobId = jobInstance.getId(); Assert.notNull(jobId, "JobId cannot be null"); Object[] parameters = new Object[] { jobId }; diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcStepExecutionDao.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcStepExecutionDao.java index bc6b12cfa..42f897753 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcStepExecutionDao.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcStepExecutionDao.java @@ -88,8 +88,9 @@ public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao private DataFieldMaxValueIncrementer stepExecutionIncrementer; - public ExecutionContext findExecutionContext(final Long executionId) { + public ExecutionContext findExecutionContext(final StepExecution stepExecution) { + final Long executionId = stepExecution.getId(); Assert.notNull(executionId, "ExecutionId must not be null."); final ExecutionContext executionContext = new ExecutionContext(); @@ -152,8 +153,10 @@ public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao * attributes that don't match a provided type must be serialized into a * blob. */ - public void saveExecutionContext(final Long executionId, final ExecutionContext executionContext) { + public void saveExecutionContext(final StepExecution stepExecution) { + final Long executionId = stepExecution.getId(); + final ExecutionContext executionContext = stepExecution.getExecutionContext(); Assert.notNull(executionId, "ExecutionId must not be null."); Assert.notNull(executionContext, "The ExecutionContext must not be null."); @@ -265,8 +268,10 @@ public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao * * @see {@link LobCreator} */ - public void updateExecutionContext(final Long executionId, ExecutionContext executionContext) { + public void updateExecutionContext(final StepExecution stepExecution) { + Long executionId = stepExecution.getId(); + ExecutionContext executionContext = stepExecution.getExecutionContext(); Assert.notNull(executionId, "ExecutionId must not be null."); Assert.notNull(executionContext, "The ExecutionContext must not be null."); diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JobExecutionDao.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JobExecutionDao.java index a84825f94..f3be2a3e5 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JobExecutionDao.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JobExecutionDao.java @@ -33,13 +33,11 @@ public interface JobExecutionDao { void updateJobExecution(JobExecution jobExecution); /** - * Return the number of JobExecutions with the given jobInstanceId + * Return the number of JobExecutions for the given JobInstance * * Preconditions: jobInstance must have an id. - * - * @param jobInstanceId */ - int getJobExecutionCount(Long jobInstanceId); + int getJobExecutionCount(JobInstance jobInstance); /** * Return list of JobExecutions for given JobInstance. diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/MapJobDao.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/MapJobDao.java index 7f01829f0..45fdfe4cb 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/MapJobDao.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/MapJobDao.java @@ -66,8 +66,8 @@ public class MapJobDao implements JobInstanceDao, JobExecutionDao { return list; } - public int getJobExecutionCount(Long jobId) { - Set executions = (Set) executionsById.get(jobId); + public int getJobExecutionCount(JobInstance jobInstance) { + Set executions = (Set) executionsById.get(jobInstance.getId()); if (executions==null) return 0; return executions.size(); } diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/MapStepDao.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/MapStepDao.java index c9e8f77ad..40bfe648c 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/MapStepDao.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/MapStepDao.java @@ -152,16 +152,14 @@ public class MapStepDao implements StepInstanceDao, StepExecutionDao { // no-op } - public ExecutionContext findExecutionContext(Long executionId) { + public ExecutionContext findExecutionContext(StepExecution stepExecution) { return null; } - public void saveExecutionContext(Long executionId, - ExecutionContext executionContext) { + public void saveExecutionContext(StepExecution stepExecution) { } - public void updateExecutionContext(Long executionId, - ExecutionContext executionContext) { + public void updateExecutionContext(StepExecution stepExecution) { } public StepExecution getLastStepExecution(StepInstance stepInstance, JobExecution jobExecution) { diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/StepExecutionDao.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/StepExecutionDao.java index 65bf3ed39..948d148d6 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/StepExecutionDao.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/StepExecutionDao.java @@ -44,7 +44,7 @@ public interface StepExecutionDao { * {@link ExecutionContext} will be returned. * @throws IllegalArgumentException if the id is null. */ - ExecutionContext findExecutionContext(final Long executionId); + ExecutionContext findExecutionContext(StepExecution stepExecution); /** * Save the provided {@link ExecutionContext} for the given executionId. @@ -54,7 +54,7 @@ public interface StepExecutionDao { * @throws IllegalArgumentException if the executionId or attributes are * null. */ - void saveExecutionContext(final Long executionId, final ExecutionContext executionContext); + void saveExecutionContext(StepExecution stepExecution); /** * Update the provided ExecutionContext. @@ -62,7 +62,7 @@ public interface StepExecutionDao { * @param executionId * @param executionContext */ - void updateExecutionContext(final Long executionId, ExecutionContext executionContext); + void updateExecutionContext(StepExecution stepExecution); /** * @param lastJobExecution last job execution diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/MockStepDao.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/MockStepDao.java index ea1250176..f3eefce6f 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/MockStepDao.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/MockStepDao.java @@ -75,16 +75,14 @@ public class MockStepDao implements StepInstanceDao, StepExecutionDao { return null; } - public ExecutionContext findExecutionContext(Long executionId) { + public ExecutionContext findExecutionContext(StepExecution stepExecution) { return null; } - public void saveExecutionContext(Long executionId, - ExecutionContext executionContext) { + public void saveExecutionContext(StepExecution stepExecution) { } - public void updateExecutionContext(Long executionId, - ExecutionContext executionContext) { + public void updateExecutionContext(StepExecution stepExecution) { } public Entity getStepExecution(Long stepExecutionId, diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/SimpleJobRepositoryTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/SimpleJobRepositoryTests.java index ca7baf480..a56ee6df1 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/SimpleJobRepositoryTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/SimpleJobRepositoryTests.java @@ -184,8 +184,8 @@ public class SimpleJobRepositoryTests extends TestCase { // and the executions in the list contain one with an end date execution.setEndTime(new Date(System.currentTimeMillis())); - Entity databaseStep1Exec = new StepExecution(databaseStep1, execution, new Long(1)); - Entity databaseStep2Exec = new StepExecution(databaseStep2, execution, new Long(2)); + StepExecution databaseStep1Exec = new StepExecution(databaseStep1, execution, new Long(1)); + StepExecution databaseStep2Exec = new StepExecution(databaseStep2, execution, new Long(2)); List jobs = new ArrayList(); jobInstanceDao.findJobInstances(jobConfiguration.getName(), jobParameters); @@ -195,7 +195,7 @@ public class SimpleJobRepositoryTests extends TestCase { stepInstanceDaoControl.setReturnValue(databaseStep1); stepExecutionDao.getLastStepExecution(databaseStep1, jobExecution); stepExecutionDaoControl.setReturnValue(databaseStep1Exec); - stepExecutionDao.findExecutionContext(databaseStep1Exec.getId()); + stepExecutionDao.findExecutionContext(databaseStep1Exec); stepExecutionDaoControl.setReturnValue(executionContext); stepExecutionDao.getStepExecutionCount(databaseStep1); stepExecutionDaoControl.setReturnValue(1); @@ -203,13 +203,13 @@ public class SimpleJobRepositoryTests extends TestCase { stepInstanceDaoControl.setReturnValue(databaseStep2); stepExecutionDao.getLastStepExecution(databaseStep2, jobExecution); stepExecutionDaoControl.setReturnValue(databaseStep2Exec); - stepExecutionDao.findExecutionContext(databaseStep2Exec.getId()); + stepExecutionDao.findExecutionContext(databaseStep2Exec); stepExecutionDaoControl.setReturnValue(executionContext); stepExecutionDao.getStepExecutionCount(databaseStep2); stepExecutionDaoControl.setReturnValue(1); stepExecutionDaoControl.replay(); stepInstanceDaoControl.replay(); - jobExecutionDao.getJobExecutionCount(databaseJob.getId()); + jobExecutionDao.getJobExecutionCount(databaseJob); jobExecutionDaoControl.setReturnValue(1); jobExecutionDao.findJobExecutions(databaseJob); jobExecutionDaoControl.setReturnValue(executions); @@ -269,7 +269,7 @@ public class SimpleJobRepositoryTests extends TestCase { jobInstanceDao.findJobInstances(jobConfiguration.getName(), jobParameters); jobs.add(databaseJob); jobInstanceDaoControl.setReturnValue(jobs); - jobExecutionDao.getJobExecutionCount(databaseJob.getId()); + jobExecutionDao.getJobExecutionCount(databaseJob); // return a greater execution count then the start limit, should throw // exception jobExecutionDaoControl.setReturnValue(2); @@ -361,7 +361,7 @@ public class SimpleJobRepositoryTests extends TestCase { ExecutionContext executionContext = new ExecutionContext(); stepExecution.setExecutionContext(executionContext); stepExecutionDao.updateStepExecution(stepExecution); - stepExecutionDao.updateExecutionContext(stepExecution.getId(), executionContext); + stepExecutionDao.updateExecutionContext(stepExecution); stepExecutionDaoControl.replay(); jobRepository.saveOrUpdate(stepExecution); stepExecutionDaoControl.verify(); @@ -372,7 +372,7 @@ public class SimpleJobRepositoryTests extends TestCase { ExecutionContext executionContext = new ExecutionContext(); stepExecution.setExecutionContext(executionContext); stepExecutionDao.saveStepExecution(stepExecution); - stepExecutionDao.saveExecutionContext(stepExecution.getId(), executionContext); + stepExecutionDao.saveExecutionContext(stepExecution); stepExecutionDaoControl.replay(); jobRepository.saveOrUpdate(stepExecution); stepExecutionDaoControl.verify(); @@ -433,8 +433,8 @@ public class SimpleJobRepositoryTests extends TestCase { public void testFindStepsFixesInvalidExecutionContext() throws Exception { - Entity databaseStep1Exec = new StepExecution(databaseStep1, null, new Long(1)); - Entity databaseStep2Exec = new StepExecution(databaseStep2, null, new Long(2)); + StepExecution databaseStep1Exec = new StepExecution(databaseStep1, null, new Long(1)); + StepExecution databaseStep2Exec = new StepExecution(databaseStep2, null, new Long(2)); List jobs = new ArrayList(); jobInstanceDao.findJobInstances(jobConfiguration.getName(), jobParameters); @@ -444,7 +444,7 @@ public class SimpleJobRepositoryTests extends TestCase { stepInstanceDaoControl.setReturnValue(databaseStep1); stepExecutionDao.getLastStepExecution(databaseStep1, null); stepExecutionDaoControl.setReturnValue(databaseStep1Exec); - stepExecutionDao.findExecutionContext(databaseStep1Exec.getId()); + stepExecutionDao.findExecutionContext(databaseStep1Exec); stepExecutionDaoControl.setReturnValue(executionContext); stepExecutionDao.getStepExecutionCount(databaseStep1); stepExecutionDaoControl.setReturnValue(1); @@ -452,14 +452,14 @@ public class SimpleJobRepositoryTests extends TestCase { stepInstanceDaoControl.setReturnValue(databaseStep2); stepExecutionDao.getLastStepExecution(databaseStep2, null); stepExecutionDaoControl.setReturnValue(databaseStep2Exec); - stepExecutionDao.findExecutionContext(databaseStep2Exec.getId()); + stepExecutionDao.findExecutionContext(databaseStep2Exec); stepExecutionDaoControl.setReturnValue(executionContext); stepExecutionDao.getStepExecutionCount(databaseStep2); stepExecutionDaoControl.setReturnValue(1); stepExecutionDaoControl.replay(); stepInstanceDaoControl.replay(); - jobExecutionDao.getJobExecutionCount(databaseJob.getId()); + jobExecutionDao.getJobExecutionCount(databaseJob); jobExecutionDaoControl.setReturnValue(1); jobExecutionDao.findJobExecutions(databaseJob); jobExecutionDaoControl.setReturnValue(new ArrayList()); diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractJobDaoTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractJobDaoTests.java index f61e3ca1f..2cb429ac4 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractJobDaoTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractJobDaoTests.java @@ -199,20 +199,20 @@ public abstract class AbstractJobDaoTests extends public void testIncrementExecutionCount() { // 1 JobExection already added in setup - assertEquals(jobExecutionDao.getJobExecutionCount(jobInstance.getId()), 1); + assertEquals(jobExecutionDao.getJobExecutionCount(jobInstance), 1); // Save new JobExecution for same job JobExecution testJobExecution = new JobExecution(jobInstance); jobExecutionDao.saveJobExecution(testJobExecution); // JobExecutionCount should be incremented by 1 - assertEquals(jobExecutionDao.getJobExecutionCount(jobInstance.getId()), 2); + assertEquals(jobExecutionDao.getJobExecutionCount(jobInstance), 2); } public void testZeroExecutionCount() { JobInstance testJob = jobInstanceDao.createJobInstance("test", new JobParameters()); // no jobExecutions saved for new job, count should be 0 - assertEquals(jobExecutionDao.getJobExecutionCount(testJob.getId()), 0); + assertEquals(jobExecutionDao.getJobExecutionCount(testJob), 0); } public void testJobWithSimpleJobIdentifier() throws Exception { diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractStepDaoTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractStepDaoTests.java index 25cf9f47f..40bd45a34 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractStepDaoTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractStepDaoTests.java @@ -99,7 +99,7 @@ public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSour jobExecution = new JobExecution(step2.getJobInstance()); jobExecutionDao.saveJobExecution(jobExecution); - stepExecution = new StepExecution(step1, jobExecution, null); + stepExecution = new StepExecution(step1, jobExecution, new Long(1)); stepExecution.setStatus(BatchStatus.STARTED); stepExecution.setStartTime(new Date(System.currentTimeMillis())); stepExecutionDao.saveStepExecution(stepExecution); @@ -153,10 +153,10 @@ public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSour } public void testUpdateStepWithExecutionContext() { - - stepExecutionDao.saveExecutionContext(step1.getId(), executionContext); + stepExecution.setExecutionContext(executionContext); + stepExecutionDao.saveExecutionContext(stepExecution); StepInstance tempStep = stepInstanceDao.findStepInstance(jobInstance, step1.getName()); - ExecutionContext tempAttributes = stepExecutionDao.findExecutionContext(step1.getId()); + ExecutionContext tempAttributes = stepExecutionDao.findExecutionContext(stepExecution); assertEquals(tempStep, step1); assertEquals(executionContext, tempAttributes); } @@ -245,13 +245,13 @@ public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSour } public void testSaveExecutionContext(){ - - stepExecutionDao.saveExecutionContext(stepExecution.getId(), executionContext); - ExecutionContext attributes = stepExecutionDao.findExecutionContext(stepExecution.getId()); + stepExecution.setExecutionContext(executionContext); + stepExecutionDao.saveExecutionContext(stepExecution); + ExecutionContext attributes = stepExecutionDao.findExecutionContext(stepExecution); assertEquals(executionContext, attributes); executionContext.putString("newString", "newString"); - stepExecutionDao.updateExecutionContext(stepExecution.getId(), executionContext); - attributes = stepExecutionDao.findExecutionContext(stepExecution.getId()); + stepExecutionDao.updateExecutionContext(stepExecution); + attributes = stepExecutionDao.findExecutionContext(stepExecution); assertEquals(executionContext, attributes); } diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/MapJobDaoTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/MapJobDaoTests.java index ae935ba6a..3106d0313 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/MapJobDaoTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/MapJobDaoTests.java @@ -50,7 +50,7 @@ public class MapJobDaoTests extends TestCase { public void testNoExecutionsForNewJob() throws Exception { JobInstance job = dao.createJobInstance("foo", jobParameters); - assertEquals(0, dao.getJobExecutionCount(job.getId())); + assertEquals(0, dao.getJobExecutionCount(job)); } public void testSaveExecutionUpdatesId() throws Exception { @@ -63,7 +63,7 @@ public class MapJobDaoTests extends TestCase { public void testCorrectExecutionCountForExistingJob() throws Exception { JobInstance job = dao.createJobInstance("foo", jobParameters); dao.saveJobExecution(new JobExecution(job)); - assertEquals(1, dao.getJobExecutionCount(job.getId())); + assertEquals(1, dao.getJobExecutionCount(job)); } public void testMultipleExecutionsPerExisting() throws Exception { @@ -71,7 +71,7 @@ public class MapJobDaoTests extends TestCase { dao.saveJobExecution(new JobExecution(job)); Thread.sleep(50L); // Hack, hack, hackety, hack - job executions are not unique if created too close together! dao.saveJobExecution(new JobExecution(job)); - assertEquals(2, dao.getJobExecutionCount(job.getId())); + assertEquals(2, dao.getJobExecutionCount(job)); } public void testGetJobExecution(){