tags:

views:

79

answers:

3

Can anybody tell me why is this method not working?

String strQuery = "Insert Into cust_subs (CustomerId,SubscriptionId) Values (?,?)";
PreparedStatement objPreparedStatement = Utils.getPreparedStatement(objConnection, strQuery);
objPreparedStatement.setInt(2, currentSubscriptions.get(0) );

where currentSubscriptions is:

List<Integer> currentSubscriptions;

I get this error even though it is Integer list:-

SEVERE: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

Assume that connection object already exists. And i am very sure that currentSubscriptions is not null else i wouldn't have got this error. If instead of using List i hardcode like this:

objPreparedStatement.setInt(2,1);

It works. I have even printed the values of List using System.out.println and it's perfectly fine. They are integers only. Don't know why is it treating them as Strings. I have even tried Integer.parseInt on list's item. Still it gives me the same error. This is one of the funniest errors I have ever faced.

Thanks in advance :)

EDIT :-

Atleast this should work. But even this is not working :-

  int intSubscriptionId = Integer.parseInt( currentSubscriptions.get(0).toString());

            objPreparedStatement.setInt(2, intSubscriptionId );

EDIT 2:

Posting whole code :-

package beans;

import entities.Customer;
import entities.Subscription;
import java.io.IOException;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import misc.Utils;

@ManagedBean
@ViewScoped
public class AddSubscriptionBean implements Serializable {

    private Customer customer;
    private List<Integer> currentSubscriptions;
    private List<Subscription> subscriptionList;

    public List<Subscription> getSubscriptionList() {
        return subscriptionList;
    }

    public void setSubscriptionList(List<Subscription> subscriptionList) {
        this.subscriptionList = subscriptionList;
    }

    public List<Integer> getCurrentSubscriptions() {
        return currentSubscriptions;
    }

    public void setCurrentSubscriptions(List<Integer> currentSubscriptions) {
        this.currentSubscriptions = currentSubscriptions;
    }

    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
    }

    /** Creates a new instance of AddSubscriptionBean */
    public AddSubscriptionBean() throws IOException, SQLException {

        Connection objConnection = null;
        try {
            HttpServletRequest objHttpServletRequest = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
            int intCustomerId = Integer.parseInt(objHttpServletRequest.getParameter("cid"));
            String strQuery = "Select * from customer Where CustomerID = " + intCustomerId;

            ResultSet objResultSet = Utils.executeResultSet(objConnection, strQuery);
            if (objResultSet.next()) {
                String strFirstName = objResultSet.getString("FirstName");
                String strLastName = objResultSet.getString("LastName");
                customer = new Customer(intCustomerId, strFirstName, strLastName);
            }

            currentSubscriptions = new ArrayList<Integer>();

            for (Subscription objSubscription : customer.getSubscriptionList()) {
                currentSubscriptions.add(objSubscription.getSubscriptionId());
            }


            subscriptionList = new ArrayList<Subscription>();
            strQuery = "Select * from subscription";
            objResultSet = Utils.executeResultSet(objConnection, strQuery);
            while (objResultSet.next()) {
                int intSubscriptionId = objResultSet.getInt("SubscriptionId");
                String strSubsriptionTitle = objResultSet.getString("Title");
                String strSubsriptionType = objResultSet.getString("Type");
                Subscription objSubscription = new Subscription(intSubscriptionId, strSubsriptionTitle, strSubsriptionType);
                subscriptionList.add(objSubscription);
            }


        } catch (Exception ex) {
            ex.printStackTrace();
            FacesContext.getCurrentInstance().getExternalContext().redirect("index.jsf");
        } finally {
            if (objConnection != null) {
                objConnection.close();
            }
        }
    }

    public void save() throws SQLException {

        Connection objConnection = null;
        Savepoint objSavepoint = null;
        try {
            objConnection = Utils.getConnection();
            objConnection.setAutoCommit(false);
            objSavepoint = objConnection.setSavepoint();
            String strQuery = "Delete From cust_subs Where CustomerId = " + customer.getCustomerId();

            if (!Utils.executeQuery(objConnection, strQuery)) {
                throw new Exception();
            }

            strQuery = "Insert Into cust_subs (CustomerId,SubscriptionId) Values (?,?)";


            int intCustomerId = customer.getCustomerId();
            PreparedStatement objPreparedStatement = Utils.getPreparedStatement(objConnection, strQuery);
            for (int intIndex = 0; intIndex < currentSubscriptions.size(); intIndex++) {
                objPreparedStatement.setInt(1, intCustomerId);
                int intSubscriptionId = Integer.parseInt( currentSubscriptions.get(0).toString());

                objPreparedStatement.setInt(2, intSubscriptionId );
                objPreparedStatement.addBatch();
            }

            objPreparedStatement.executeBatch();

            objConnection.commit();
        } catch (Exception ex) {
            ex.printStackTrace();
            if (objConnection != null) {
                objConnection.rollback(objSavepoint);
            }
        } finally {
            if (objConnection != null) {
                objConnection.close();
            }
        }
    }
}

This is my JSF page :-

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:msc="http://mscit/jsf"&gt;
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <center>
            <h:form>
            <h1>Add Subscription</h1>

            <b> Customer Name :</b> <h:outputText value="#{addSubscriptionBean.customer.firstName} #{addSubscriptionBean.customer.lastName}"/>

            <h:selectManyCheckbox value="#{addSubscriptionBean.currentSubscriptions}">

                <f:selectItems value="#{addSubscriptionBean.subscriptionList}" var="row" itemLabel="#{row.title}" itemValue="#{row.subscriptionId}" />

            </h:selectManyCheckbox>

            <h:commandButton value="Save" actionListener="#{addSubscriptionBean.save}"/>
            </h:form>
        </center>
    </h:body>
</html>

Please look at the h:selectManyCheckbox of JSF. JSF internally passes all the checkboxes that i have checked to my List. I think JSF is converting my integer list to string.

A: 

Nevermind. x10000000000000000000

BobTurbo
What is this? Is this your answer? :-/
Ankit Rathod
@Nitesh, he initially said you should be using a concrete class. However, that's not the issue, so he changed the answer. @Bob, you should be able to delete your answer. See [the details](http://meta.stackoverflow.com/questions/5221/what-can-cause-a-post-to-be-deleted-and-what-does-that-actually-mean).
Matthew Flaschen
Yeah I have not yet registered, so cannot delete my posts.
BobTurbo
+3  A: 

It's possible to put Strings into a List<Integer> if you use unsafe operations:

List<Integer> intList = new ArrayList<Integer>();
List list = intList;
list.add("1");

intList and list hold references to the same list, which now contains a string. As you've seen, you get a ClassCastException upon trying to extract the element from intList.

Java generics work using hidden casting, and you can defeat the type-checking. To test this, assign to a List, then print the class of every element:

List currentSubscriptionsUnsafe = currentSubscriptions;
for(Object o : currentSubscriptionsUnsafe)
{
  System.out.println(o.getClass());
}

EDIT: I'm not familiar with JSF, but I think your guess is correct. One solution is to make currentSubscriptions a List<String> everywhere (which JSF seems to expect). Then, get(0) will return a String, which you can parse into an Integer. There may be a cleaner method, but this should work.

Matthew Flaschen
But i am not doing any such thing. How do i get rid of this? What changes do i need to make instead of list?
Ankit Rathod
@Nitesh, print the class of every element using that code. That will tell you if this is the issue.
Matthew Flaschen
Hi Matthew, Yes indeed this is the problem. I get this :- `INFO: class java.lang.String`. How can i solve this? Why is it being oversmart? even though i pass integers in it?
Ankit Rathod
@Nitesh, post more of your code (anything somehow connected to `currentSubscriptions`). You clearly have an unsafe reference somewhere, and you are adding a String using that.
Matthew Flaschen
Hi Matthew Flaschen, please read my edited post. Atleast the `edited` code should work? But even that is not working.
Ankit Rathod
@Nitesh, no. Because `currentSubscriptions` is a `List<Integer>` reference, `get(0)` has a hidden cast to `Integer`. So you're trying to cast a `String` to an `Integer`, then call `toString`. But the cast is still not allowed. You need to prevent the `String` from being added in the first place. Please show more code, specifically any code related to this list.
Matthew Flaschen
Great! Works :). But i still didn't understand your above comment Integer.parseInt will return a primitive type value and it is always a int only. Don't know why just changing List from Integer to String works.
Ankit Rathod
He is refering to currentSubscriptions.get(0), not parseInt. The get method will try to convert the String's in your List to integers, which it cannot do. So making the list List<String> and calling get on the list will not try to convert to Integers.
BobTurbo
@BobTurbo, i was talking about my edited code. Can you tell me how can this ever return anything other than int? `int intSubscriptionId = Integer.parseInt(currentSubscriptions.get(0).toString());`? I always thought Integer.parseInt will always return a primitive type `int`. No matter what the internal references are but Integer.parseInt should always return a primitive `int` type value. I must admit this is one of the most strange errors i have faced till today and not easy for me to digest.
Ankit Rathod
It will always return an int, but int intSubscriptionId = Integer.parseInt(currentSubscriptions.get(0).toString()); is now where the error occurs (instead of the next line). As the error is in currentSubscription.get(0). So you have just shifted the error up a line.
BobTurbo
@Nitesh, when `currentSubscriptions` was a `List<Integer>`, that line internally became: `int intSubscriptionId = Integer.parseInt(((Integer)(currentSubscriptions.get(0))).toString());`. You were still casting a `String` to an `Integer`, which is an error.
Matthew Flaschen
Thanks Matthew Flaschen. Got it!
Ankit Rathod
While technically correct, the proposed solution is in JSF context not a real solution but more a workaround. I certainly wouldn't use it.
BalusC
Hi BalusC, thanks for your valuable comments. Did you later on happen to give a thought on creating JSF composite components using JQuery? Netbeans 6.9 is out and it's fine.
Ankit Rathod
+2  A: 

You need to instruct h:selectManyCheckbox to convert the values to Integer by specifying javax.faces.Integer as converter. Generic types are namely unknown in EL and it treats the parameters by default as String.

<h:selectManyCheckbox converter="javax.faces.Integer">

No need to use List<String> instead which would only lead to more weaktype clutter in the bean.

BalusC
Thanks exactly what i was looking for!
Ankit Rathod