I'm working on a simple Spring MVC web app that allows users to encrypt and decrypt messages with classical ciphers such as the shift or Caesar cipher. It also allows users to auto-decrypt a message using crypt-analysis and to press an example button that randomly pulls an example, for any given cipher, from a database. The 4 ciphers are Shift, Affine, Substitution, and Vigenere. Each cipher has plain text, cipher text, and a key(s). The key(s) can be integers or strings.I have the following concerns about my app:My controller has 3 routes for each cipher. One is a GET for when the user navigates to the page. Another is POST with a direction for encrypting, decrypting, or auto-decrypting. The last is a GET for an example of a cipher.  I've tried handling things in a better polymorphic way, but haven't had success, mostly due to the fact that ciphers can have one or multiple keys.My shift classes that contain the business logic are stateless and it seems unnecessary to create an object when all of the methods could just be static.Similar to #2, I've considered getting rid of the Value Objects and instead just have a POJO with the cipher business logic in it. However, my understanding is that a bean should not have business logic. Therefore, I separated the VO and the classes that contain the business logic for the ciphers.For the Shift and Affine Cipher, the keys (the shift amounts) have a specific boundary. The key for Shift has to be numbers 1-26 while Affine has to be a number relatively prime to 26. This is business logic and should not be defined in the view. Therefore, I made an array for the valid shift amounts that a user can enter. This array is a static final variable on my Domain Model. It is passed to the view and the view renders a drop down for each element in the array. In the case of an Affine Cipher, this would be the numbers relatively prime to 26. I'd appreciate insight on how I could handle this business logic.I'll show relative code for a Shift Cipher.ShiftVOpublic class ShiftVO {    private String plainText, cipherText;    private int shiftAmount;    private int [] validShifts; //The possible shifts that a user can perform with a Shift Cipher (1-26)    public String getPlainText() {        return plainText;    }    public void setPlainText(String plainText) {        this.plainText = plainText;    }    public String getCipherText() {        return cipherText;    }    public void setCipherText(String cipherText) {        this.cipherText = cipherText;    }    public int getShiftAmount() {        return shiftAmount;    }    public void setShiftAmount(int shiftAmount) {        this.shiftAmount = shiftAmount;    }    public int[] getValidShifts() {        return validShifts;    }    public void setValidShifts(int[] validShifts) {        this.validShifts = validShifts;    }}ShiftCipher - Business logic for a shift cipher. As noted in #3 I'm considering getting rid of this class or make the methods static. public class ShiftCipher {    public final static int [] VALID_SHIFTS = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26};    public String encrypt(String plainText, int shiftAmount) {        //performs encryption    }    public String decrypt(String cipherText, int shiftAmount) {        //performs decryption    }    public int autoDecrypt(String cipherText) {        //performs auto decryption    }}CipherDAO - used to get a random cipher from the database as an example for the user@Component(cipherDao)public class CipherDao {    private SimpleJdbcCall procReadCipher;    @Autowired    public void setDataSource(DataSource jdbc) {        this.procReadCipher= new SimpleJdbcCall(jdbc);    }    public ShiftVO getRandShift(){        SqlParameterSource in = new MapSqlParameterSource();        procReadCipher.withProcedureName(usp_S_rnd_ex_shift_cipher);        Map<String, Object> out = procReadCipher.execute(in);        System.out.println(out.values());        System.out.println(out.values().size());        ShiftVO shiftVO = new ShiftVO();        shiftVO.setCipherText((String) out.get(cipher_text));        shiftVO.setPlainText((String) out.get(plain_text));        shiftVO.setShiftAmount((Integer) out.get(shift_amount));        return shiftVO;    }}RandomCipherService - Service for communication to the DAO to retrieve random ciphers for examples@Service(randomCipherService)public class RandomCipherService {    private CipherDao cipherDao;    @Autowired    public void setOffersDao(CipherDao cipherDao) {        this.cipherDao = cipherDao;    }    public ShiftVO getRandomShift(){            return cipherDao.getRandShift();    }}CipherService@Service(cipherService)public class CipherService {    public enum CipherDirection {        ENCRYPT, DECRYPT, AUTODECRYPT    }    public void shift(ShiftVO shiftVO, CipherDirection cipherDirection){        ShiftCipher shiftCipher = new ShiftCipher();        try{            if(cipherDirection == CipherDirection.ENCRYPT){                String cipherText = shiftCipher.encrypt(shiftVO.getPlainText(), shiftVO.getShiftAmount());                shiftVO.setCipherText(cipherText);            } else if(cipherDirection == CipherDirection.DECRYPT){                String plainText = shiftCipher.decrypt(shiftVO.getCipherText(), shiftVO.getShiftAmount());                shiftVO.setPlainText(plainText);            } else if(cipherDirection == CipherDirection.AUTODECRYPT){                int shiftAmount = shiftCipher.autoDecrypt(shiftVO.getCipherText());                String plainText = shiftCipher.decrypt(shiftVO.getCipherText(), shiftAmount);                shiftVO.setPlainText(plainText);                shiftVO.setShiftAmount(shiftAmount);            } //Still need to add IllegalArgumentException        } catch(Exception e){            System.out.println(Error:  + e);        }    }}CipherController    @Controllerpublic class CipherController {    private CipherService cipherService;    private RandomCipherService randomCipherService;    @Autowired    public void setCipherService(CipherService cipherService) {        this.cipherService = cipherService;    }    @Autowired    public void setRandomCipherService(RandomCipherService randomCipherService) {        this.randomCipherService = randomCipherService;    }    @RequestMapping(value={,/,/shift})    public String showShift(Model model){            ShiftVO shiftVO = new ShiftVO();            shiftVO.setValidShifts(cipherService.getShiftValidShifts());            model.addAttribute(shift,shiftVO);            return shift;    }    @RequestMapping(value=/shift, method=RequestMethod.POST)    public String shiftCipher(ShiftVO shiftVO                        , @RequestParam(cipherDirection) String cipherDirection                        , Model model) {        cipherService.shift(shiftVO, CipherDirection.valueOf(cipherDirection));        shiftVO.setValidShifts(cipherService.getShiftValidShifts());        model.addAttribute(shift,shiftVO);        return shift;    }    @RequestMapping(value=/randomshift)    public String randomShiftCipher(Model model){        System.out.println(random shift);        ShiftVO shiftVO = randomCipherService.getRandomShift();        shiftVO.setValidShifts(cipherService.getShiftValidShifts());        model.addAttribute(shift,shiftVO);        System.out.println(shiftVO.getPlainText());        return shift;    }}shift.jsp<%@ page language=java contentType=text/html; charset=ISO-8859-1    pageEncoding=ISO-8859-1%><%@ taglib prefix=sf uri=http://www.springframework.org/tags/form %><%@ taglib prefix=c uri=http://java.sun.com/jsp/jstl/core %><%@ taglib prefix=fmt uri=http://java.sun.com/jsp/jstl/fmt %><!DOCTYPE html PUBLIC -//W3C//DTD HTML 4.01 Transitional//EN http://www.w3.org/TR/html4/loose.dtd><html><head><meta http-equiv=Content-Type content=text/html; charset=ISO-8859-1>    <title>Classical Cipher</title>    <link href=${pageContext.request.contextPath}/assets/css/cipher.css rel=stylesheet type=text/css></head><body>    <nav id = navbar-ciphers>      <h2>Ciphers</h2>      <hr>      <ul class = menu>        <li><a href=${pageContext.request.contextPath}/shift>Shift</a></li>           <li><a href=${pageContext.request.contextPath}/affine>Affine</a></li>                     <li><a href=${pageContext.request.contextPath}/substitution>Substitution</a></li>           <li><a href=${pageContext.request.contextPath}/vigenere>Vigenere</a></li>         </ul>    </nav>    <div id=main-content>      <div id=cipher-input>      <sf:form method=post action=${pageContext.request.contextPath}/shift commandName=shift>        <div id =shift-cipher-input class=selected-cipher>          <label> Shift Amount: </label>          <select name=shiftAmount id=shift-amount>            <c:forEach var=validShift items=${shift.validShifts}>                <option value=${validShift} ${validShift == shift.shiftAmount ? 'selected' : ''}>${validShift}</option>            </c:forEach>          </select>        </div>        <br>        <label>Plain Text</label>        <br>        <textarea name=plainText id=plain-text placeholder=Plain text><c:out value=${shift.plainText}></c:out></textarea>        <br>        <label>Cipher Text</label>        <br>        <textarea name=cipherText id=cipher-text placeholder=Cipher text><c:out value=${shift.cipherText}></c:out></textarea>        <br>        <button type=submit id=encrypt name=cipherDirection value=ENCRYPT>Encrypt</button>        <button type=submit id=decrypt name=cipherDirection value=DECRYPT>Decrypt</button>        <button type=submit id=auto-decrypt name=cipherDirection value=AUTODECRYPT>Auto Decrypt</button>        <input type=button id=clear-ciphers value = Clear>     </sf:form>     <input type=button  onclick=${pageContext.request.contextPath}/randomshift value=Randomshift>    <form action=<c:url value=/randomshift /> method=GET>        <input type=submit name=action value=Random />     </form>     </div>    </div>    <script type=text/javascript src=https://code.jquery.com/jquery-2.2.1.min.js></script>    <script type=text/javascript src=https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js></script>    <script type=text/javascript src=${pageContext.request.contextPath}/assets/js/cipher.js></script></body></html>
Spring MVC web app for simple ciphers
java;object oriented;caesar cipher;spring;spring mvc