¿Por qué obtengo “Excepción”? debe ser capturado o declarado lanzado “cuando bash comstackr mi código Java?

Considerar:

import java.awt.*; import javax.swing.*; import java.awt.event.*; import javax.crypto.*; import javax.crypto.spec.*; import java.security.*; import java.io.*; public class EncryptURL extends JApplet implements ActionListener { Container content; JTextField userName = new JTextField(); JTextField firstName = new JTextField(); JTextField lastName = new JTextField(); JTextField email = new JTextField(); JTextField phone = new JTextField(); JTextField heartbeatID = new JTextField(); JTextField regionCode = new JTextField(); JTextField retRegionCode = new JTextField(); JTextField encryptedTextField = new JTextField(); JPanel finishPanel = new JPanel(); public void init() { //setTitle("Book - E Project"); setSize(800, 600); content = getContentPane(); content.setBackground(Color.yellow); content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS)); JButton submit = new JButton("Submit"); content.add(new JLabel("User Name")); content.add(userName); content.add(new JLabel("First Name")); content.add(firstName); content.add(new JLabel("Last Name")); content.add(lastName); content.add(new JLabel("Email")); content.add(email); content.add(new JLabel("Phone")); content.add(phone); content.add(new JLabel("HeartBeatID")); content.add(heartbeatID); content.add(new JLabel("Region Code")); content.add(regionCode); content.add(new JLabel("RetRegionCode")); content.add(retRegionCode); content.add(submit); submit.addActionListener(this); } public void actionPerformed(ActionEvent e) { if (e.getActionCommand() == "Submit"){ String subUserName = userName.getText(); String subFName = firstName.getText(); String subLName = lastName.getText(); String subEmail = email.getText(); String subPhone = phone.getText(); String subHeartbeatID = heartbeatID.getText(); String subRegionCode = regionCode.getText(); String subRetRegionCode = retRegionCode.getText(); String concatURL = "user=" + subUserName + "&f=" + subFName + "&l=" + subLName + "&em=" + subEmail + "&p=" + subPhone + "&h=" + subHeartbeatID + "&re=" + subRegionCode + "&ret=" + subRetRegionCode; concatURL = padString(concatURL, ' ', 16); byte[] encrypted = encrypt(concatURL); String encryptedString = bytesToHex(encrypted); content.removeAll(); content.add(new JLabel("Concatenated User Input -->" + concatURL)); content.add(encryptedTextField); setContentPane(content); } } public static byte[] encrypt(String toEncrypt) throws Exception{ try{ String plaintext = toEncrypt; String key = "01234567890abcde"; String iv = "fedcba9876543210"; SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES"); IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes()); Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec); byte[] encrypted = cipher.doFinal(toEncrypt.getBytes()); return encrypted; } catch(Exception e){ } } public static byte[] decrypt(byte[] toDecrypt) throws Exception{ String key = "01234567890abcde"; String iv = "fedcba9876543210"; SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES"); IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes()); Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec); byte[] decrypted = cipher.doFinal(toDecrypt); return decrypted; } public static String bytesToHex(byte[] data) { if (data == null) { return null; } else { int len = data.length; String str = ""; for (int i=0; i<len; i++) { if ((data[i]&0xFF) < 16) str = str + "0" + java.lang.Integer.toHexString(data[i]&0xFF); else str = str + java.lang.Integer.toHexString(data[i]&0xFF); } return str; } } public static String padString(String source, char paddingChar, int size) { int padLength = size-source.length() % size; for (int i = 0; i < padLength; i++) { source += paddingChar; } return source; } } 

Recibo una excepción no reportada:

 java.lang.Exception; must be caught or declared to be thrown byte[] encrypted = encrypt(concatURL); 

Tanto como:

 .java:109: missing return statement 

¿Cómo resuelvo estos problemas?

Todos tus problemas derivan de esto

 byte[] encrypted = cipher.doFinal(toEncrypt.getBytes()); return encrypted; 

Los cuales están encerrados en un bloque try, catch, el problema es que, en caso de que el progtwig encuentre una excepción, no está devolviendo nada. Ponlo así (modifícalo como se encuentra la lógica de tu progtwig):

 public static byte[] encrypt(String toEncrypt) throws Exception{ try{ String plaintext = toEncrypt; String key = "01234567890abcde"; String iv = "fedcba9876543210"; SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES"); IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes()); Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE,keyspec,ivspec); byte[] encrypted = cipher.doFinal(toEncrypt.getBytes()); return encrypted; } catch(Exception e){ return null; // Always must return something } } 

Para el segundo, debe atrapar la Excepción de la llamada al método de cifrado, así (también modifíquela a medida que se encuentre la lógica de su progtwig):

 public void actionPerformed(ActionEvent e) . . . try { byte[] encrypted = encrypt(concatURL); String encryptedString = bytesToHex(encrypted); content.removeAll(); content.add(new JLabel("Concatenated User Input -->" + concatURL)); content.add(encryptedTextField); setContentPane(content); } catch (Exception exc) { // TODO: handle exception } } 

Las lecciones que debes aprender de esto:

  • Un método con un tipo de retorno siempre debe devolver un objeto de ese tipo, es decir, en todos los escenarios posibles
  • Todas las excepciones marcadas siempre deben ser manejadas

El problema está en este método:

  public static byte[] encrypt(String toEncrypt) throws Exception{ 

Esta es la firma del método que más o menos dice:

  • cuál es el nombre del método: encriptar
  • qué parámetro recibe: una cadena llamada aEncrypt
  • su modificador de acceso: public static
  • y si puede lanzar o no una excepción cuando se invoca.

En este caso, la firma del método dice que cuando se invoca este método “podría” lanzar una excepción del tipo “Excepción”.

  .... concatURL = padString(concatURL, ' ', 16); byte[] encrypted = encrypt(concatURL); <-- HERE!!!!! String encryptedString = bytesToHex(encrypted); content.removeAll(); ...... 

Así que los comstackdores dicen: O rodean eso con una construcción try / catch o declaran el método (dónde se está usando) para arrojar "Exception".

El verdadero problema es la definición del método "cifrar". Ningún método debería devolver "Excepción", porque es demasiado genérico y puede ocultar algunos otros tipos de excepción, es mejor tener una excepción específica.

Prueba esto:

 public static byte[] encrypt(String toEncrypt) { try{ String plaintext = toEncrypt; String key = "01234567890abcde"; String iv = "fedcba9876543210"; SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES"); IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes()); Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE,keyspec,ivspec); byte[] encrypted = cipher.doFinal(toEncrypt.getBytes()); return encrypted; } catch ( NoSuchAlgorithmException nsae ) { // What can you do if the algorithm doesn't exists?? // this usually won't happen because you would test // your code before shipping. // So in this case is ok to transform to another kind throw new IllegalStateException( nsae ); } catch ( NoSuchPaddingException nspe ) { // What can you do when there is no such padding ( whatever that means ) ?? // I guess not much, in either case you won't be able to encrypt the given string throw new IllegalStateException( nsae ); } // line 109 won't say it needs a return anymore. } 

Básicamente en este caso particular, debe asegurarse de que el paquete de criptografía esté disponible en el sistema.

Java necesita una extensión para el paquete de criptografía, por lo tanto, las excepciones se declaran como excepciones "controladas". Para que puedas manejar cuando no están presentes.

En este pequeño progtwig, no puede hacer nada si el paquete de criptografía no está disponible, por lo que lo verifica en el momento del "desarrollo". Si esas excepciones se producen cuando se está ejecutando su progtwig es porque hizo algo mal en "desarrollo", por lo tanto, una subclase RuntimeException es más apropiada.

La última línea ya no necesita una statement de devolución, en la primera versión que estaba capturando la excepción y sin hacer nada con ella, eso está mal.

 try { // risky code ... } catch( Exception e ) { // a bomb has just exploited // you should NOT ignore it } // The code continues here, but what should it do??? 

Si el código falla, es mejor fallar rápido

Aquí hay algunas respuestas relacionadas:

  • Captura de excepciones en Java

  • Cuándo elegir las excepciones marcadas y no marcadas

  • ¿Por qué no tienes que declarar explícitamente que puedes arrojar algunas excepciones integradas en Java?

  • Excepción distinta de RuntimeException

El primer error

java.lang.Exception; debe capturarse o declararse lanzada byte [] encrypted = encrypt (concatURL);

significa que su método de encrypt arroja una excepción que no está siendo manejada o declarada por el método actionPerformed donde la está llamando. Lea todo al respecto en el tutorial de excepciones de Java .

Tiene un par de opciones que puede elegir para obtener el código para comstackr.

  • Puedes eliminar throws Exception de tu método de encrypt y manejar la excepción dentro de encrypt .
  • Puede eliminar el bloque try / catch de encrypt y add throws Exception y el bloque de manejo de excepciones para su método actionPerformed .

Por lo general, es mejor manejar una excepción en el nivel más bajo posible, en lugar de pasarla a un nivel superior.

El segundo error solo significa que debe agregar una statement de devolución a cualquier método que contenga la línea 109 (también encrypt , en este caso). Hay una statement de devolución en el método, pero si se lanza una excepción, es posible que no se llegue a ella, por lo que debe regresar al bloque catch o eliminar el try / catch de encrypt , como mencioné anteriormente.

Deberá decidir cómo le gustaría manejar las excepciones lanzadas por el método de encrypt .

Actualmente, el encrypt se declara con throws Exception ; sin embargo, en el cuerpo del método, las excepciones quedan atrapadas en un bloque try / catch. Te recomiendo:

  • elimine la cláusula de throws Exception de encrypt y manejar excepciones internamente ( considere escribir un mensaje de registro como mínimo ); o,
  • elimine el bloque try / catch del cuerpo del encrypt y rodee la llamada para encrypt con un try / catch en su lugar (es decir, en actionPerformed ).

Con respecto al error de comstackción, consulte: si se lanzó una excepción en el bloque try de encrypt , no se devuelve nada después de que finaliza el bloque catch . Puede abordar esto declarando inicialmente el valor de retorno como null :

 public static byte[] encrypt(String toEncrypt) throws Exception{ byte[] encrypted = null; try { // ... encrypted = ... } catch(Exception e){ // ... } return encrypted; } 

Sin embargo, si puede corregir el problema mayor (la estrategia de manejo de excepciones), este problema se resolverá solo, especialmente si elige la segunda opción que he sugerido.

En su método de “encriptación”, debe deshacerse del try / catch y en su lugar agregar try / catch alrededor de donde llama a encrypt (dentro de “actionPerformed”) o devolver null dentro del catch dentro de encrypt (ese es el segundo error).

En actionPerformed(ActionEvent e) llama a encrypt() , que se declara para lanzar Exception . Sin embargo, actionPerformed no actionPerformed esta excepción (con try / catch alrededor de la llamada para encrypt() ) ni declara que arroja la Exception sí misma.

Su método de encrypt , sin embargo, no arroja Exception . Se traga todas las excepciones sin siquiera tanto como registrar una queja. (Mala práctica y mal estilo!)

Además, su método de encrypt hace lo siguiente:

 public static byte[] encrypt(String toEncrypt) throws Exception { try{ .... return encrypted; // HERE YOU CORRECTLY RETURN A VALUE } catch(Exception e) { } // YOU DO NOT RETURN ANYTHING HERE } 

Es decir, si captas cualquier excepción, la descartas en silencio y luego caes al final de tu método de encrypt sin devolver nada. Esto no se comstackrá (como puede ver), porque un método que se declara para devolver un valor debe devolver un valor o lanzar una excepción para cada ruta de código posible.