error while committing the transaction error in spring mvc? - spring

HibernateSpatialJPA class:
public class HibernateSpatialJPA {
private static final EntityManagerFactory emFactory;
static {
try {
emFactory = Persistence.createEntityManagerFactory("org.hibernate.events.jpa");
}catch(Throwable ex){
System.err.println("Cannot create EntityManagerFactory.");
throw new ExceptionInInitializerError(ex);
}
}
public static EntityManager createEntityManager() {
return emFactory.createEntityManager();
}
public static void close(){
emFactory.close();
}
}
this is manager class:
public class SavegeojsonManager {
SavegeojsonEntity theEvent = new SavegeojsonEntity();
public boolean insert(JSONObject json)
{
GeoJSON item = new GeoJSON(json);
return insert(item);
}
public boolean insert(GeoJSON item)
{
boolean success=false;
try {
String vectorType = item.getType();
EntityManager em = HibernateSpatialJPA.createEntityManager();
em.getTransaction().begin();
theEvent.setVectorType(vectorType);
em.persist(theEvent);
em.getTransaction().commit();
em.close();
success=true;
}
catch (Exception ex) {
System.out.println(ex.getMessage());
success = false;
}
HibernateSpatialJPA.close();
return success;
}
}
and this is GeoJsonClass :
public class GeoJSON
{
private int id;
private String type;
private String data;
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getType() {return type;}
public void setType(String type) {this.type = type;}
public String getData() {return data;}
public void setData(String data) { this.data = data; }
public GeoJSON() {
}
public GeoJSON(JSONObject json) {
parse(json);
}
public GeoJSON parse(JSONObject json) {
StringWriter out = new StringWriter();
json.write(out);
this.data = out.toString();
this.type = json.getString("type");
try {
out.close();
} catch (IOException ex) {
System.out.println(ex.getMessage());
throw new RuntimeException(ex);
}
return this;
}
}
But I am not able to save into database because error :
enter code here : "error while committing the transaction."
Do you have any idea about this error ?
Below is the Exception stack trace:-
javax.persistence.RollbackException: Error while committing the transaction
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:92)
at com.springapp.model.SavegeojsonManager.insert(SavegeojsonManager.java:32)
at com.springapp.model.SavegeojsonManager.insert(SavegeojsonManager.java:19)
at com.springapp.mvc.HSpatialController.saveGeoJson(HSpatialController.java:46)
...
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: ERROR: column "vectortype" of relation "savegeojson" does not exist Position: 76 at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1377) at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1300) at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:80) ... 40 more Caused by: org.hibernate.exception.SQLGrammarException: ERROR: column "vectortype" of relation "savegeojson" does not exist Position: 76 at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:122) at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110) at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129) at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81) at com.sun.proxy.$Proxy26.executeUpdate(Unknown Source) at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:56) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2962) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3403) at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:88) at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362) at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354) at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:275) at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326) at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52) at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1214) at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:403) at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101) at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175) at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:75) ... 40 more Caused by: org.postgresql.util.PSQLException: ERROR: column "vectortype" of relation "savegeojson" does not exist Position: 76 at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2062) at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1795) at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257) at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:479) at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:367) at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:321) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122) ... 56 more

You are saving Entity SavegeojsonEntity to postgresql db and this error means:
Caused by: org.postgresql.util.PSQLException: ERROR: column "vectortype" of relation "savegeojson" does not exist
Position: 76
Table that SavegeojsonEntity are mapped to does not have column vectortype. Check in your db that column exists in table.
If it does not exist you need to add that column to table.

Related

Mockito tests pass except one verify

I have all my tests pass except this line in the first test
verify(reimbursementDAO).getById(REIMBURSEMENT_TO_PROCESS.getId());
see code below.
package com.revature.services;
public class ReimbursementServiceTest {
private static ReimbursementService reimbursementService;
private static ReimbursementDAO reimbursementDAO;
private Reimbursement REIMBURSEMENT_TO_PROCESS;
private Reimbursement GENERIC_REIMBURSEMENT_1;
private Optional<Reimbursement>
GENERIC_REIMBURSEMENT_2;
private List<Reimbursement> GENERIC_ALL_PENDING_REIMBURSEMENTS;
private User GENERIC_EMPLOYEE_1;
private User GENERIC_FINANCE_MANAGER_1;
#BeforeClass
public static void setUpBeforeClass() throws Exception {
reimbursementDAO=mock(ReimbursementDAO.class);//(IReimbursementDAO.class);
reimbursementService = new ReimbursementService(reimbursementDAO);
//reimbursementDAO=new ReimbursementDAO();
}
#Before
public void setUp() throws Exception {
GENERIC_EMPLOYEE_1 = new User(1, "genericEmployee1", "genericPassword", Role.EMPLOYEE);
GENERIC_FINANCE_MANAGER_1 = new User(1, "genericManager1", "genericPassword", Role.FINANCE_MANAGER);
REIMBURSEMENT_TO_PROCESS = new Reimbursement(2, Status.PENDING, GENERIC_EMPLOYEE_1, null, 150.00);
GENERIC_REIMBURSEMENT_1 = new Reimbursement(1, Status.PENDING, GENERIC_EMPLOYEE_1, null, 100.00);
GENERIC_REIMBURSEMENT_2 = Optional.ofNullable(new Reimbursement(2, Status.APPROVED, GENERIC_EMPLOYEE_1,
GENERIC_FINANCE_MANAGER_1, 150.00));
GENERIC_ALL_PENDING_REIMBURSEMENTS = new ArrayList<Reimbursement>();
GENERIC_ALL_PENDING_REIMBURSEMENTS.add(GENERIC_REIMBURSEMENT_1);
}
#Test
public void testProcessPassesWhenUserIsFinanceManagerAndReimbursementExistsAndUpdateSuccessful()
throws Exception{
when(reimbursementDAO.getById(anyInt())).thenReturn(Optional.of(GENERIC_REIMBURSEMENT_1));
when(reimbursementDAO.update(any())).thenReturn(GENERIC_REIMBURSEMENT_2);
assertEquals(GENERIC_REIMBURSEMENT_2,
reimbursementService.process(REIMBURSEMENT_TO_PROCESS, Status.APPROVED,
GENERIC_FINANCE_MANAGER_1));
//verify(reimbursementDAO).getById(REIMBURSEMENT_TO_PROCESS.getId());
verify(reimbursementDAO).update(REIMBURSEMENT_TO_PROCESS);
}
#Test
public void testGetReimbursementByStatusPassesWhenReimbursementsAreSuccessfullyReturned() {
when(reimbursementDAO.getBystatus(any())).thenReturn(GENERIC_ALL_PENDING_REIMBURSEMENTS);
assertEquals(GENERIC_ALL_PENDING_REIMBURSEMENTS,
reimbursementService.getReimbursementsByStatus(Status.PENDING));
verify(reimbursementDAO).getBystatus(Status.PENDING);
}
}
public class ReimbursementDAO extends AbstractReimbursement
{
public Optional< Reimbursement> getById(int id) {
try(Connection conn = ConnectionFactory.getConnection())
{
String sql="select * from ers_reimbursements where reimb_id=?;";
PreparedStatement ps=conn.prepareStatement(sql);
ps.setInt(1,id);
ResultSet rs= ps.executeQuery();
Reimbursement reimb=null;
UserService usrv=new UserService();
//reimb_id ,amount, submitted,resolved,description,author,receipt ,resolver,status,reimb_type
while(rs.next())
{
int reid=rs.getInt("reimb_id");
double ramount=rs.getInt("reimb_amount");
int res=rs.getInt( "resolver");
User resolver=null;
String description=rs.getString("description");
User rauthor= usrv.getUserById( rs.getInt("author")).get();
if(res>0)
{ resolver= usrv.getUserById(res).get(); }
int rstatus= rs.getInt("reimb_status");
Status r_status=Status.values()[--rstatus];
int reimb_type= rs.getInt("reimb_type");
ReimbType retype=ReimbType.values()[--reimb_type];
User oth=rauthor;
User re=resolver;
reimb=new Reimbursement(reid, r_status,oth,re,ramount);
return Optional.ofNullable(reimb);
}
}catch(SQLException e) { e.printStackTrace();};
return Optional.empty();
}
public List<Reimbursement> getBystatus(Status status) {
try(Connection conn = ConnectionFactory.getConnection())
{
String sql="select * from ers_reimbursements where reimb_status=?;";
PreparedStatement ps=conn.prepareStatement(sql);//,Statement.RETURN_GENERATED_KEYS);
int sta_id= status.ordinal()+1;
ps.setInt(1,sta_id);
ResultSet rs= ps.executeQuery();
Reimbursement reimb=null;
List<Reimbursement> reimbList=new ArrayList<Reimbursement>();
IUserService usrv=new UserService();
//reimb_id ,amount, submitted,resolved,description,author,receipt ,resolver,status,reimb_type
while(rs.next())
{
//int id, Status status, User author, User resolver, double amount
int reid=rs.getInt("reimb_id");
double ramount=rs.getInt("reimb_amount");
Optional<User> rauthor= usrv.getUserById( rs.getInt("author"));
User oth=null;
if(rauthor.isPresent())
{ oth=rauthor.get(); }
int resol=rs.getInt( "resolver");
Optional<User> resolver= usrv.getUserById(resol);
User re=null;
if(resolver.isPresent())
{ re=resolver.get(); }
else {re=null;}
int rstatus= rs.getInt("reimb_status");
Status r_status=Status.values()[--rstatus];//.PENDING;
int reimb_type= rs.getInt("reimb_type");
ReimbType retype=ReimbType.values()[--reimb_type];//.TRAVEL;
reimb=new Reimbursement(reid, r_status,oth,re,ramount);
reimbList.add(reimb);
}
return reimbList;
}catch(SQLException e) { e.printStackTrace();};
return null;
}
public Optional<Reimbursement> update(Reimbursement unprocessedReimbursement) {
try(Connection conn=ConnectionFactory.getConnection()) {
String sql="update ers_reimbursements set reimb_status=?,"
+ " resolver=?, resolved=? where reimb_id=?;";
PreparedStatement ps=conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
int id=unprocessedReimbursement.getId();
Status st=unprocessedReimbursement.getStatus();
ps.setObject(1,st);
ps.setInt(2,unprocessedReimbursement.getResolver().getId());
ps.setObject(3, LocalDateTime.now());
ps.setInt(4,id);
ps.executeUpdate();
try (ResultSet generatedKeys = ps.getGeneratedKeys()) {
if (generatedKeys.next()) {
int reimid=generatedKeys.getInt(1);
Optional<Reimbursement> reim=getById(reimid);
System.out.println("Reimb " + reim.get()+ " upLocalTimed!");
return reim;
}
}catch(SQLException e) {};
}catch(SQLException e) { e.printStackTrace();}
return Optional.empty();
}
}
public class ReimbursementService{
{
private final ReimbursementDAO reimbDao;
public ReimbursementService() {
this(new ReimbursementDAO());
}
public ReimbursementService(ReimbursementDAO userDAO2) {
this.reimbDao = userDAO2;
}
public Optional< Reimbursement> process(Reimbursement unprocessedReimbursement,
Status finalStatus, User resolver) throws Exception{
if (!resolver.getRole().equals(Role.FINANCE_MANAGER)) {
throw new RegistrationUnsuccessfulException("Resolver must be Finance Manager ");
}
// List<Reimbursement> l=DAO.getByStatus(Status.PENDING);
if(unprocessedReimbursement.getId()==0)
{ throw new Exception(" reimbursement not found"); }
if(unprocessedReimbursement.getStatus().equals(Status.PENDING))
{
unprocessedReimbursement.setResolver(resolver);
unprocessedReimbursement.setStatus(finalStatus);
Optional<Reimbursement> reimb=this.reimbDao.update(unprocessedReimbursement );
if(reimb.isPresent())
{ return reimb; }
else { throw new Exception("unsuccessful update");}
}
return Optional.ofNullable(null);
}
}
The verification
verify(reimbursementDAO).getById(REIMBURSEMENT_TO_PROCESS.getId());
fails because your service does not call the getById() method of your DAO.
It happens that your real DAO's update() method calls its own getById() method, but in your test you are using a mock DAO, where all functionality has been stubbed out. The update() method of the mock DAO does nothing more than return GENERIC_REIMBURSEMENT_2 because that's what your test sets it up to do.

SpringBoot+JDBCTemplate+Parent Key not found error

Unable to insert into child table in a single transaction using springboot and jdbctemplate.
Controller:
#RequestMapping(value = "/addUser", method = RequestMethod.POST)
public Response addUser(#RequestBody UserVo userVo) throws Exception
{
service.addUserRecord(userVo);
}
Service Layer:
#Autowired
private Dao dao;
#Transactional(readOnly = false)
public void addUserRecord(#RequestBody UserVo userVo) throws Exception
{
int parentSeqNo = dao.addUser();
int result = dao.addUserDetails(parentSeqNo, list);
}
DAOImple class:
#Autowired
private JdbcTemplate jdbcTemplate;
public int addUser()
{
try
{
String sql = "INSERT INTO user_table() VALUES (?,?,?,?,?) ";
jdbcTemplate.update(sql,....);
return seqNo;
}
catch(Exception e)
{
e.printStackTrace();
throw e;
}
}
public void addUserDetails(String seqNo, List<String> list){
String sql="insert into user_details_table values(?,?)";
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
public void setValues(PreparedStatement ps, int i) throws SQLException {
String img = list.get(i);
ps.setString(1, seqNo);
ps.setString(2, img);
}
public int getBatchSize() {
return list.size();
}
});
return;
}
Issue/Error:
ORA-02291: integrity constraint (FK3) violated - parent key not found; nested exception is java.sql.SQLIntegrityConstraintViolationException:
Database tables and constraints are looks good and tried to insert using sql editor, just working fine. While testing from postman tool, getting parent key not found exception. Greatly appreciated for any suggestions on this issue.

How to make Hibernate use setFixedCHAR instead of setString

Can I somehow modify the way Hibernate binds parameters to the query?
For example, I want hibernate to use OracleResultSet.setFixedChar() when executing on an string column, instead of rs.setString() when executing a JPA query via Spring data.
This is how I would do it without Hibernate:
try(PreparedStatement ps = con.executeQuery("...")) {
if(ps.isWrapped(OraclePreparedStatement.class) {
ps.unwrap(OraclePreparedStatement.class).setFixedCHAR(0, myStringField);
} else {
ps.setString(0, myStringField);
}
try(ResultSet rs = ps.getResultSet()) {
while(rs.next()) {
... do stuff ...
}
}
}
Repository method (Spring data JPA):
List<Object> findByMyStringField(String myStringField);
How can I influence how Hibernate binds my variable. With the above example setString is used always.
As background: the problem is that all our Legacy DB's use CHAR columns and not VARCHAR2, so we have to deal with whitespace and setFixedCHAR should do exactly what we would want.
Found a solution by implementing a SqlTypeDescriptor & Custom Dialect:
#Autowired
private DataSource source;
#Bean
public HibernateJpaVendorAdapter getHibernateJPAVendorAdapter() {
return new CustomHibernateJpaVendorAdaptor();
}
private static class CustomHibernateJpaVendorAdaptor extends HibernateJpaVendorAdapter {
#Override
protected Class<?> determineDatabaseDialectClass(Database database) {
// if HSQL is copied from Spring Sourcecode to keep everything the same
if (Database.HSQL.equals(database)) {
return CustomHsqlDialect.class;
}
try {
if (source.isWrapperFor(OracleDataSource.class)) {
return CustomOracleDialect.class;
}
} catch (SQLException e) {
}
return super.determineDatabaseDialectClass(database);
}
private class CustomHsqlDialect extends HSQLDialect {
public CustomHsqlDialect() {
registerColumnType(Types.BOOLEAN, "boolean");
registerHibernateType(Types.BOOLEAN, "boolean");
}
}
}
#NoArgsConstructor
public static class CustomOracleDialect extends Oracle12cDialect {
private static final OracleCharFix INSTANCE = new OracleCharFix();
#Override
protected SqlTypeDescriptor getSqlTypeDescriptorOverride(final int sqlCode) {
switch (sqlCode) {
case Types.VARCHAR:
return INSTANCE;
default:
return super.getSqlTypeDescriptorOverride(sqlCode);
}
}
}
#Slf4j
private static class OracleCharFix extends CharTypeDescriptor {
#Override
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicBinder<>(javaTypeDescriptor, this) {
#Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
if (st.isWrapperFor(OraclePreparedStatement.class)) {
OraclePreparedStatement ops = st.unwrap(OraclePreparedStatement.class);
if (ops.getParameterMetaData().getParameterType(index) == Types.CHAR) {
ops.setFixedCHAR(index, javaTypeDescriptor.unwrap(value, String.class, options));
} else {
st.setString(index, javaTypeDescriptor.unwrap(value, String.class, options));
}
} else {
st.setString(index, javaTypeDescriptor.unwrap(value, String.class, options));
}
}
#Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
//Is nolonger used by Hibernate in the current Version
st.setString(name, javaTypeDescriptor.unwrap(value, String.class, options));
}
private boolean checkIfCHARByName(ResultSetMetaData metadata, String name)
throws SQLException {
for (int i = 1; i <= metadata.getColumnCount(); i++) {
if (metadata.getColumnType(i) == Types.CHAR && Objects.equals(metadata.getColumnName(i), name)) {
return true;
}
}
return false;
}
};
}

Glassfish RAR5035:Unexpected Exception While Destroying Resource From Pool

I have a Java EE web application. I am connecting database with JDBC and I am using JDBC connection pool. My application's main page is login page. After I enter the login page and wait for a while, I take this glassfish server(4.1.0) warning consistently.
Warning: RAR5035:Unexpected exception while destroying resource from
pool OraclePool. Exception message: Error while destroying resource
:IO Error: Socket read timed out
Even if I don't do any action on the page. When I monitore the statistics of the connection pool, NumConnCreated is increasing continuously. How can I solve the problem?. Thank you.
This is my managed bean class.
#ManagedBean
#SessionScoped
public class Login implements Serializable{
private String userName;
private String password;
private User user;
private #EJB DBRemote db;
public void test(){
String[] params1 = {"user","1234"};
int[] getParams = {Types.INTEGER,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR};
CallableStatement statement = db.run("TBL.USERLOGIN(?,?,?,?,?,?)", params1 , getParams);
try {
int isLogin = statement.getInt(3);
if (isLogin==1) {
String uName = statement.getString(4);
String uId = statement.getString(5);
user = new User(uId, uName, isLogin);
System.out.println("LOGGED IN " + uName + "\t" + uId);
}else{
String errMessage = statement.getString(6);
user = new User(errMessage,isLogin);
System.out.println("LOG IN FAILURE " + errMessage);
}
} catch (SQLException ex) {
Logger.getLogger(Login.class.getName()).log(Level.SEVERE, null, ex);
}finally{
db.close();
FacesContext.getCurrentInstance().addMessage("infoback", new FacesMessage(FacesMessage.SEVERITY_INFO,
"TEST","Test Works"));
}
}
}
This my interface class
#Remote
public interface DBRemote {
CallableStatement run(String query, String[] setParams, int[] getParams);
void close();
String getErrorMessage();
String getSql();
}
This is my Stateless Bean class
#Stateless
public class DB implements DBRemote{
#Resource(mappedName = "pwresource")
private DataSource ds;
private String sql;
private String errorMessage;
private CallableStatement statement;
private Connection connection;
public DB() {
}
#Override
public CallableStatement run(String query, String[] setParams, int[] getParams){
sql = "{call " + query + "}";
int getParamIndex = setParams.length + 1;
try {
connection = ds.getConnection();
statement = connection.prepareCall(sql);
for (int i = 0; i < setParams.length; i++) {
statement.setString(i+1, setParams[i]);
}
for (int getParam : getParams) {
statement.registerOutParameter(getParamIndex, getParam);
getParamIndex++;
}
statement.execute();
}catch (SQLException ex) {
if (ex.getErrorCode()==17008) {
errorMessage = "Timeout";
}else{
errorMessage = "System Error";
}
Logger.getLogger(DB.class.getName()).log(Level.SEVERE, null, ex);
close();
}
return statement;
}
#Override
public void close(){
try {
if (statement != null) {
statement.close();
}
if(connection != null){
connection.close();
}
errorMessage = null;
} catch (SQLException e) {
errorMessage = "Close Connection Error";
}
}
#Override
public String getErrorMessage() {
return errorMessage;
}
#Override
public String getSql() {
return sql;
}
}
I have solved my problem. My problem is because of the connection between connection pool and database. Database closes the connections automically because of the server and database in different networks caused timeout issue.

custom arrayadapter get data from asynctask

i trying to connect with themoviedb.orgbut there's some issues
MainActivityFragment.java
public class MainActivityFragment extends Fragment {
public Item[] dataAdapter ;
public MainActivityFragment() {
this.updateData();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add this line in order for this fragment to handle menu events.
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_fragment, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.refresh_settings) {
startActivity(new Intent(getActivity(),SettingsActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
CustomArrayAdapter adapter =new CustomArrayAdapter(this.getActivity() , R.layout.item , dataAdapter);
// Get a reference to the ListView, and attach this adapter to it.
GridView gridView = (GridView) rootView.findViewById(R.id.main_grid_view);
gridView.setAdapter(adapter);
return rootView;
}
private void updateData() {
GetData DataTask = new GetData();
DataTask.execute();
}
#Override
public void onStart() {
super.onStart();
this.updateData();
}
public class GetData extends AsyncTask<Void, Void, Item[]> {
private final String LOG_TAG = GetData.class.getSimpleName();
private Item[] getDataFromJson(String forecastJsonStr)
throws JSONException{
// These are the names of the JSON objects that need to be extracted.
final String RESULTS = "results";
final String IMG_PATH = "poster_path";
final String TITLE = "title";
JSONObject dataJson = new JSONObject(forecastJsonStr);
JSONArray dataArray = dataJson.getJSONArray(RESULTS);
int numofresults = dataArray.length();
Item[] resultStrs = new Item[0];
for(int i = 0; i < numofresults; i++) {
// For now, using the format "Day, description, hi/low"
String img_path;
String title;
JSONObject movieData = dataArray.getJSONObject(i);
img_path = movieData.getString(IMG_PATH);
img_path ="http://image.tmdb.org/t/p/w185"+img_path;
title = movieData.getString(TITLE);
Item element = new Item(img_path,title);
resultStrs[i] = element;
}
return resultStrs;
}
#Override
protected Item[] doInBackground(Void... strings) {
// These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String dataJsonStr = null;
String parm = getString(R.string.pref_sort_most);
String api_key = "API KEY";
try {
final String BASE_URL =
"http://api.themoviedb.org/3/discover/movie?";
final String QUERY_PARAM = "sort_by";
final String APPID_PARAM = "api_key";
Uri builtUri = Uri.parse(BASE_URL).buildUpon()
.appendQueryParameter(QUERY_PARAM, parm)
.appendQueryParameter(APPID_PARAM, api_key)
.build();
URL url = new URL(builtUri.toString());
// Create the request to themoviedb.org, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
dataJsonStr = buffer.toString();
} catch (IOException e) {
Log.e(LOG_TAG, "Error ", e);
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}
}
try {
return getDataFromJson(dataJsonStr);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Item[] result) {
if (result != null) {
dataAdapter = result;
}
// New data is back from the server. Hooray!
}
}
}
CustomArrayAdapter.java
public class CustomArrayAdapter extends ArrayAdapter<Item> {
Context context;
int resource;
Item objects[] = null;
public CustomArrayAdapter(Context context, int resource, Item[] objects) {
super(context, resource, objects);
this.resource = resource;
this.context = context;
this.objects = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
View row = convertView;
DataHolder holder = null;
if(row == null)
{
row = LayoutInflater.from(getContext()).inflate(
R.layout.item, parent, false);
holder = new DataHolder();
holder.imgIcon = (ImageView)row.findViewById(R.id.image_main_item);
holder.txtTitle = (TextView)row.findViewById(R.id.title_movie);
row.setTag(holder);
}else
{
holder = (DataHolder)row.getTag();
}
Item item = objects[position];
holder.txtTitle.setText(item.title);
Picasso.with(context).load(item.icon).into(holder.imgIcon);
return row;
}
static class DataHolder
{
ImageView imgIcon;
TextView txtTitle;
}
}
Item.java
public class Item {
public String icon;
public String title;
public Item(){
super();
}
public Item(String icon, String title) {
super();
this.icon = icon;
this.title = title;
}
}
and here my Logcat
12-23 15:06:40.832 1644-1644/com.example.mohamed.movieapp
E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.mohamed.movieapp, PID: 1644
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.mohamed.movieapp/com.example.mohamed.movieapp.MainActivity}:
android.view.InflateException: Binary XML file line #1: Error
inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: android.view.InflateException: Binary XML file line #1: Error inflating class fragment
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:763)
at android.view.LayoutInflater.inflate(LayoutInflater.java:482)
at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:256)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109)
at com.example.mohamed.movieapp.MainActivity.onCreate(MainActivity.java:19)
at android.app.Activity.performCreate(Activity.java:5990)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
            at android.app.ActivityThread.access$800(ActivityThread.java:151)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: java.lang.NullPointerException: storage == null
at java.util.Arrays$ArrayList.(Arrays.java:38)
at java.util.Arrays.asList(Arrays.java:155)
at android.widget.ArrayAdapter.(ArrayAdapter.java:128)
at com.example.mohamed.movieapp.CustomArrayAdapter.(CustomArrayAdapter.java:25)
at com.example.mohamed.movieapp.MainActivityFragment.onCreateView(MainActivityFragment.java:78)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1962)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1036)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1226)
at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1328)
at android.support.v4.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2284)
at android.support.v4.app.FragmentController.onCreateView(FragmentController.java:111)
at android.support.v4.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:314)
at android.support.v4.app.BaseFragmentActivityHoneycomb.onCreateView(BaseFragmentActivityHoneycomb.java:31)
at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:79)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:733)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:482)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
            at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:256)
            at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109)
            at com.example.mohamed.movieapp.MainActivity.onCreate(MainActivity.java:19)
            at android.app.Activity.performCreate(Activity.java:5990)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
            at android.app.ActivityThread.access$800(ActivityThread.java:151)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
thnks for advice and interaction
So during onCreateView which gets called early in life cylce, you are trying to create array adapter out of empty uninitialized array. Please move setAdapter call to your post execute.
Note: any particular reason to update data in constructor? You are anyway calling it onStart.

Resources