This document describes how to parse JSON data from a URL and store it in a local SQLite database in an Android application. It includes the following:
1. A JSONParser class that makes HTTP requests and handles SSL certificate verification to retrieve JSON data from a URL.
2. An OrdersActivity class that uses the JSONParser to download order data from a URL, stores it in a local DB, and displays it in a list. It includes asynchronous tasks to download and access the data without blocking the UI.
3. Details on how the JSON data is structured and parsed to extract values and store them in the database using the DBAbaco class.
So in summary, it explains how to retrieve remote
The document describes how to create a JSON parser class in Android to retrieve data from a web API without certificate checking. It includes creating a JSONParser class with methods to make HTTPS requests and parse the JSON response. It also describes an OrdersActivity that uses an AsyncTask to download order data from the API via JSONParser, save it to a local DB, and display it in a list. The OrdersActivity includes methods for the AsyncTasks to show loading dialogs and populate the list from the DB data on completion.
Soroush Khanlou discusses abstraction — what it is, and what it isn’t. We’ll step through the process of taking code that went from good to bad, and find ways to make it good again. How do we build an abstraction from code that isn’t abstract? What qualities are we looking for in our abstractions?
The document describes refactoring legacy code for a push notification daemon. It starts with a single long method that handles both pushing notifications to a queue and processing incoming requests over UDP. It goes through a series of refactoring steps like extracting methods, extracting classes, and replacing methods with objects to break the class into separate concerns and make it more extensible and maintainable. This includes creating separate Worker, UDPServer, and PushDaemon classes with clear responsibilities.
Webinar slides: How to Secure MongoDB with ClusterControlSeveralnines
Watch the slides of our webinar on “How to secure MongoDB with ClusterControl” and find out about the essential steps necessary to secure MongoDB and how to verify if your MongoDB instance is safe.
The recent MongoDB ransom hack caused a lot of damage and outages, while it could have been prevented with maybe two or three simple configuration changes. MongoDB offers a lot of security features out of the box, however it disables them by default.
In this webinar, we explain which configuration changes are necessary to enable MongoDB’s security features, and how to test if your setup is secure after enablement. We also demonstrate how ClusterControl enables security on default installations. And we cover how to leverage the ClusterControl advisors and the MongoDB Audit Log to constantly scan your environment, and harden your security even more.
AGENDA
What is the MongoDB ransom hack?
What other security threats are valid for MongoDB?
How to enable authentication / authorisation
How to secure MongoDB from ransomware
How to scan your system
ClusterControl MongoDB security advisors
Live Demo
SPEAKER
Art van Scheppingen is a Senior Support Engineer at Severalnines. He’s a pragmatic MySQL and Database expert with over 15 years experience in web development. He previously worked at Spil Games as Head of Database Engineering, where he kept a broad vision upon the whole database environment: from MySQL to Couchbase, Vertica to Hadoop and from Sphinx Search to SOLR. He regularly presents his work and projects at various conferences (Percona Live, FOSDEM) and related meetups.
This document describes the implementation of a simple REST server in Qt using reflection. It discusses how the Qt meta-object compiler (moc) is used, the abstract and concrete server classes, building the route tree using reflection, handling new connections in worker threads, calling methods based on the request, and using reflection for testing. The abstract server class inherits from QTcpServer and uses slots decorated with tags to implement routes. Worker threads handle individual connections and parse requests to call the appropriate method. Reflection is leveraged throughout to build routes and dispatch requests without explicit registration or mapping.
This presentation covers:
The main components in the connectivity path.
Best practices in your code to avoid connectivity issues.
How to solve most common connectivity problems.
DEF CON 27 - ALVARO MUNOZ / OLEKSANDR MIROSH - sso wars the token menaceFelipe Prado
The document discusses various ways that authentication tokens can be abused to bypass security protections. It describes how some implementations of token parsing and signature verification are vulnerable to arbitrary code execution or information disclosure attacks due to inconsistencies in how signing keys and security tokens are resolved from token metadata. Specific attacks are demonstrated against Windows Communication Foundation, Windows Identity Foundation, and SharePoint Server due to differences in how key and token resolution are handled for signature verification versus token authentication.
The document describes how to create a JSON parser class in Android to retrieve data from a web API without certificate checking. It includes creating a JSONParser class with methods to make HTTPS requests and parse the JSON response. It also describes an OrdersActivity that uses an AsyncTask to download order data from the API via JSONParser, save it to a local DB, and display it in a list. The OrdersActivity includes methods for the AsyncTasks to show loading dialogs and populate the list from the DB data on completion.
Soroush Khanlou discusses abstraction — what it is, and what it isn’t. We’ll step through the process of taking code that went from good to bad, and find ways to make it good again. How do we build an abstraction from code that isn’t abstract? What qualities are we looking for in our abstractions?
The document describes refactoring legacy code for a push notification daemon. It starts with a single long method that handles both pushing notifications to a queue and processing incoming requests over UDP. It goes through a series of refactoring steps like extracting methods, extracting classes, and replacing methods with objects to break the class into separate concerns and make it more extensible and maintainable. This includes creating separate Worker, UDPServer, and PushDaemon classes with clear responsibilities.
Webinar slides: How to Secure MongoDB with ClusterControlSeveralnines
Watch the slides of our webinar on “How to secure MongoDB with ClusterControl” and find out about the essential steps necessary to secure MongoDB and how to verify if your MongoDB instance is safe.
The recent MongoDB ransom hack caused a lot of damage and outages, while it could have been prevented with maybe two or three simple configuration changes. MongoDB offers a lot of security features out of the box, however it disables them by default.
In this webinar, we explain which configuration changes are necessary to enable MongoDB’s security features, and how to test if your setup is secure after enablement. We also demonstrate how ClusterControl enables security on default installations. And we cover how to leverage the ClusterControl advisors and the MongoDB Audit Log to constantly scan your environment, and harden your security even more.
AGENDA
What is the MongoDB ransom hack?
What other security threats are valid for MongoDB?
How to enable authentication / authorisation
How to secure MongoDB from ransomware
How to scan your system
ClusterControl MongoDB security advisors
Live Demo
SPEAKER
Art van Scheppingen is a Senior Support Engineer at Severalnines. He’s a pragmatic MySQL and Database expert with over 15 years experience in web development. He previously worked at Spil Games as Head of Database Engineering, where he kept a broad vision upon the whole database environment: from MySQL to Couchbase, Vertica to Hadoop and from Sphinx Search to SOLR. He regularly presents his work and projects at various conferences (Percona Live, FOSDEM) and related meetups.
This document describes the implementation of a simple REST server in Qt using reflection. It discusses how the Qt meta-object compiler (moc) is used, the abstract and concrete server classes, building the route tree using reflection, handling new connections in worker threads, calling methods based on the request, and using reflection for testing. The abstract server class inherits from QTcpServer and uses slots decorated with tags to implement routes. Worker threads handle individual connections and parse requests to call the appropriate method. Reflection is leveraged throughout to build routes and dispatch requests without explicit registration or mapping.
This presentation covers:
The main components in the connectivity path.
Best practices in your code to avoid connectivity issues.
How to solve most common connectivity problems.
DEF CON 27 - ALVARO MUNOZ / OLEKSANDR MIROSH - sso wars the token menaceFelipe Prado
The document discusses various ways that authentication tokens can be abused to bypass security protections. It describes how some implementations of token parsing and signature verification are vulnerable to arbitrary code execution or information disclosure attacks due to inconsistencies in how signing keys and security tokens are resolved from token metadata. Specific attacks are demonstrated against Windows Communication Foundation, Windows Identity Foundation, and SharePoint Server due to differences in how key and token resolution are handled for signature verification versus token authentication.
After enormous cryptocurrencies value gains this year, Blockchain - their underneath algorithm is a topic that gets both a lot of exposure and confusion among developers. In this presentation, I’m going to create a glossary that will guide you in further exploration and sort out your knowledge.
We will discuss not only what Blockchain is but also why it is (or isn’t) the big thing. Everything using easy to grasp JavaScript code examples.
Prepare yourself for surfing on dangerous hype-wave - it’s easy to drown.
Repository of Presentation:
https://github.com/ArturSkowronski/naivechain
Presented:
4Developers Łódź (https://lodz.4developers.org.pl), Kraków, 09.11.2017
KrakowJS (http://conf.krakowjs.pl/), Krakow, 29.09.2017
The document discusses configuring Tomcat connection pools. It describes preparing Tomcat by adding jar files, configuring the server.xml file and context.xml files, and testing connection pools using JSP. It also covers how Tomcat 6 supports connection pools using dbcp and how JdbcRowSet can use connection pools.
Building Your First Data Science Applicatino in MongoDBMongoDB
Speaker: Robyn Allen, Software Engineer, Central Inventions
Level: 100 (Beginner)
Track: Tutorials
To provide a hands-on opportunity to work with real data, this session will center around a web-hosted quiz application which helps students practice math and memorize vocabulary. After experimenting with a small demonstration dataset (generated by each individual during the workshop), attendees will be guided through working with an anonymized dataset in MongoDB. No prior MongoDB experience is required but attendees are expected to download and install MongoDB Community Edition (available for free from mongodb.com) and have a working Python 3 environment of their choice (e.g., IDLE, free from python.org) installed on a laptop they bring to the workshop.
Prerequisites:
Attendees are expected to bring a laptop with the following software installed:
MongoDB 3.4.x Community Edition
The text editor or IDE of their choice
A working Python 3 environment of their choice
No prior MongoDB experience is required.
What You Will Learn:
- How to load a CSV file into MongoDB using mongoimport and then write queries (using the Mongo shell) to ensure the data appears as expected. Attendees will use a demo version of an online quiz app to generate a small data file of raw session data (which can be accessed via http://strawnoodle.com/api/testdata after logging in to the demo app and answering one or more quiz questions about MongoDB). After studying how the demo app stores session data, attendees will practice using mongoimport to import anonymized session data (provided during the workshop) into MongoDB.
- How to use the aggregation pipeline (in PyMongo) to implement more complicated queries and gain insights from data. Because the sample dataset contains data from a variety of users of different skill levels, queries can be designed which reveal summary statistics for the anonymous user cohort or specific performance of individual users. Participants will receive instruction in using MongoDB aggregation pipelines in order to write powerful, efficient queries with very few lines of code.
- How to write queries to analyze sample data from an online quiz app. Once the sample data has been loaded into MongoDB, participants will be guided in writing basic queries to examine the sample data. Participants will have an opportunity to write queries in the Mongo shell and in Python in order to familiarize themselves with syntax variations and key ideas. Participants will learn how to implement CRUD operations in PyMongo.
This document contains code for a Java GUI application called EasyGUI that allows users to generate automation results for order processing. It contains classes like EasyGUI, EasyButton, and BatchEngine that create a GUI, handle button clicks, and execute automation batches. When the submit button is clicked, it validates the order ID, runs batches to get conversation IDs, account numbers, and CSIXML files, and displays the results. It uses GridBagLayout to arrange components on the main panel and stores selection values in variables like orderID and accountNumber to pass to batch processing methods.
The code examples show source code for a client and server application for a chat program. The client code defines functions for connecting to the server, sending and receiving messages. The server code defines functions for starting the server, accepting new connections from clients, and handling message receives and sends between connected clients. The code implements multi-threaded processing to concurrently handle multiple client connections to the server.
The document contains source code for a client-server application written in Java. The client code establishes a socket connection to the server, allows sending and receiving messages, and closes the connection. The server code starts by binding to a port, accepts new connections from clients, and spawns a new thread to handle each client connection concurrently. It reads and writes data from the socket and closes the connection when the client disconnects. The code includes classes for the client, server, and thread handling each client connection.
The document discusses how to not be afraid of differences in terraform plan outputs. It begins with an introduction and concludes that differences in terraform plan outputs should not be scary if you read the outputs carefully. It then provides a detailed example of a difference in security group rules to demonstrate how to interpret what will be added and removed. The example makes it clear that differences only reflect what will change and that the intended behavior can be understood from the plan output. The document advocates reading plan outputs rather than fearing them.
It's 10pm: Do You Know Where Your Writes Are?MongoDB
Speaker: Samantha Ritter, Software Engineer, MongoDB
Level: 200 (Intermediate)
Track: How We Build MongoDB
MongoDB 3.6 delivers three new features to help you develop resilient applications: retriable writes, a cluster-wide killOp command, and zombie cursor cleanup. These features share a common base, an idea called a logical session. This new cluster-wide concept of user state is the quiet magic that allows you to know, with certainty, the status of your operations. MongoDB engineer Samantha Ritter will describe the above features in-depth, discuss when and how logical sessions can be used by applications and administrators, and show you how we implemented sessions for large, distributed systems.
What You Will Learn:
- What logical sessions are and how they are implemented in the server
- How to leverage logical sessions for retriable writes
- How to pull the new cluster-wide killOp emergency break
Secure Communications with VisualWorks - CSTUC 2006Martin Kobetic
The document discusses secure communication techniques including:
1) Setting up a certificate authority to issue server and client certificates, and storing certificates and private keys securely on disk.
2) Configuring a secure HTTPS web server using the issued certificates for authentication and encryption.
3) Configuring an HTTPS client to authenticate with the server using the trusted certificate authority and optionally using client certificates for authentication to the server.
4) Considering performance aspects like enabling persistent connections and session resumption to improve efficiency of secure connections.
This document provides information about registering and authenticating with a Touch ID authenticator on a MacBook Pro using the Web Authentication API and FIDO2 standards. It includes code samples and explanations of the registration, attestation, and assertion response objects and flows. Key points covered include how Touch ID returns a packed SELF attestation in the registration response and includes attestedCredentialData in the early Chrome versions, which has since been fixed.
The document contains source code for a client-server chat application written in Java. The client code establishes a socket connection to the server, reads user input and sends messages to the server. The server code initializes a server socket to listen for client connections, spawns a new thread for each client, reads incoming messages and sends responses. The code includes graphical user interface components for selecting the client or server role, composing and displaying messages.
The document discusses building lightweight web APIs with .NET using Nancy. It introduces Nancy and REST concepts like resources, representations, and HTTP verbs. It provides an example of building a RESTful order management API for a coffee shop called Restbucks using Nancy. The API allows clients to place, view, cancel, and pay for orders. Nancy provides a lightweight and readable way to build RESTful services that can be hosted in various environments and is easy to test.
2019-10-05 - Untangled - Voxxed days ticinoArnaud Bos
Concurrent programming borrows a lot of terms from weaving and twists our minds with intertwined concepts: fibers, threads, lightweight-threads, green threads, loom...
Maybe you've heard about coroutines? Don't worry, everything is linked.
During this talk, we'll get weaving, show code samples and talk about project Loom, whose goal is to bring "lightweight concurrency" mechanisms to the JVM, along with APIs to embroider the story.
We will talk about project Loom's inception and recent prototypes. You will also see its mesh goes far beyond "simple" primitives to revolutionize the JVM.
This document describes how to configure Spring Security for authentication and authorization in a web application. It defines a WebSecurityConfig class that configures HTTP security with roles like OWNER and MANAGER for access control. It also defines a UserDetailsManager service for loading users and a User entity class implementing UserDetails. Tests are shown for security configuration, login, access control and more using Spring Security's test utilities.
The document provides an overview of Groovy and Java code examples for performing common tasks like printing "Hello World", reading files, making web requests, using strings, importing packages, and using Swing/SwingBuilder for GUIs. It also shows examples of using Groovy with Java libraries for Excel files, Ant, and JSON. Additional sections cover parallel processing with GPars, contract programming with GContracts, method chaining, Grails basics, and Gaelyk controllers and views.
The document discusses debugging performance problems in MongoDB. It describes solutions tried such as denormalizing data, adding indexes, sharding, scaling hardware, and tagging shards. While performance improved with these solutions at times, slowness still occasionally occurred. The document advocates using monitoring tools like New Relic and Skylight to further analyze issues and find additional solutions.
So you’ve developed an app in MongoDB Stitch? Now what? What is day-to-day use of MongoDB Stitch really like? We’ll talk topics like multi-environment deployment (dev → test → production); logging; testing and timing; and how to best make MongoDB and Stitch work for your application.
It's silly to write the same functionality over and over again. Auth is the most often implemented functionality at web projects. Let's check how can we speed up development by using one of auth provider: Amazon Cognito, Google Firebase or Auth0. On code level we will use custom React Hooks.
The document describes how to create an Android project in Eclipse to call a JSON web service. It includes:
1. Creating a new Android project called "TestJSONWebService" targeting Android 2.2 with an activity called "TestWebServiceActivity" and package name "parallelminds.webservice.com".
2. The main activity, TestWebServiceActivity, makes a call to the web service using the callWebService() method and parses the JSON response to populate a list view.
3. A second class, CallWebService, implements the call to the web service and returns the JSON response.
Securing your Pulsar Cluster with Vault_Chris KelloggStreamNative
Learn how to secure a Pulsar cluster with Hashicorp Vault and deploy it on Kubernetes. Vault provides a secure way to generate tokens and store sensitive data and Pulsar has a pluggable architecture for authentication, authorization and secret management. This talk will walk through how to create custom plugins for Vault, integrate them with Pulsar and then deploy a Pulsar cluster on Kubernetes.
After enormous cryptocurrencies value gains this year, Blockchain - their underneath algorithm is a topic that gets both a lot of exposure and confusion among developers. In this presentation, I’m going to create a glossary that will guide you in further exploration and sort out your knowledge.
We will discuss not only what Blockchain is but also why it is (or isn’t) the big thing. Everything using easy to grasp JavaScript code examples.
Prepare yourself for surfing on dangerous hype-wave - it’s easy to drown.
Repository of Presentation:
https://github.com/ArturSkowronski/naivechain
Presented:
4Developers Łódź (https://lodz.4developers.org.pl), Kraków, 09.11.2017
KrakowJS (http://conf.krakowjs.pl/), Krakow, 29.09.2017
The document discusses configuring Tomcat connection pools. It describes preparing Tomcat by adding jar files, configuring the server.xml file and context.xml files, and testing connection pools using JSP. It also covers how Tomcat 6 supports connection pools using dbcp and how JdbcRowSet can use connection pools.
Building Your First Data Science Applicatino in MongoDBMongoDB
Speaker: Robyn Allen, Software Engineer, Central Inventions
Level: 100 (Beginner)
Track: Tutorials
To provide a hands-on opportunity to work with real data, this session will center around a web-hosted quiz application which helps students practice math and memorize vocabulary. After experimenting with a small demonstration dataset (generated by each individual during the workshop), attendees will be guided through working with an anonymized dataset in MongoDB. No prior MongoDB experience is required but attendees are expected to download and install MongoDB Community Edition (available for free from mongodb.com) and have a working Python 3 environment of their choice (e.g., IDLE, free from python.org) installed on a laptop they bring to the workshop.
Prerequisites:
Attendees are expected to bring a laptop with the following software installed:
MongoDB 3.4.x Community Edition
The text editor or IDE of their choice
A working Python 3 environment of their choice
No prior MongoDB experience is required.
What You Will Learn:
- How to load a CSV file into MongoDB using mongoimport and then write queries (using the Mongo shell) to ensure the data appears as expected. Attendees will use a demo version of an online quiz app to generate a small data file of raw session data (which can be accessed via http://strawnoodle.com/api/testdata after logging in to the demo app and answering one or more quiz questions about MongoDB). After studying how the demo app stores session data, attendees will practice using mongoimport to import anonymized session data (provided during the workshop) into MongoDB.
- How to use the aggregation pipeline (in PyMongo) to implement more complicated queries and gain insights from data. Because the sample dataset contains data from a variety of users of different skill levels, queries can be designed which reveal summary statistics for the anonymous user cohort or specific performance of individual users. Participants will receive instruction in using MongoDB aggregation pipelines in order to write powerful, efficient queries with very few lines of code.
- How to write queries to analyze sample data from an online quiz app. Once the sample data has been loaded into MongoDB, participants will be guided in writing basic queries to examine the sample data. Participants will have an opportunity to write queries in the Mongo shell and in Python in order to familiarize themselves with syntax variations and key ideas. Participants will learn how to implement CRUD operations in PyMongo.
This document contains code for a Java GUI application called EasyGUI that allows users to generate automation results for order processing. It contains classes like EasyGUI, EasyButton, and BatchEngine that create a GUI, handle button clicks, and execute automation batches. When the submit button is clicked, it validates the order ID, runs batches to get conversation IDs, account numbers, and CSIXML files, and displays the results. It uses GridBagLayout to arrange components on the main panel and stores selection values in variables like orderID and accountNumber to pass to batch processing methods.
The code examples show source code for a client and server application for a chat program. The client code defines functions for connecting to the server, sending and receiving messages. The server code defines functions for starting the server, accepting new connections from clients, and handling message receives and sends between connected clients. The code implements multi-threaded processing to concurrently handle multiple client connections to the server.
The document contains source code for a client-server application written in Java. The client code establishes a socket connection to the server, allows sending and receiving messages, and closes the connection. The server code starts by binding to a port, accepts new connections from clients, and spawns a new thread to handle each client connection concurrently. It reads and writes data from the socket and closes the connection when the client disconnects. The code includes classes for the client, server, and thread handling each client connection.
The document discusses how to not be afraid of differences in terraform plan outputs. It begins with an introduction and concludes that differences in terraform plan outputs should not be scary if you read the outputs carefully. It then provides a detailed example of a difference in security group rules to demonstrate how to interpret what will be added and removed. The example makes it clear that differences only reflect what will change and that the intended behavior can be understood from the plan output. The document advocates reading plan outputs rather than fearing them.
It's 10pm: Do You Know Where Your Writes Are?MongoDB
Speaker: Samantha Ritter, Software Engineer, MongoDB
Level: 200 (Intermediate)
Track: How We Build MongoDB
MongoDB 3.6 delivers three new features to help you develop resilient applications: retriable writes, a cluster-wide killOp command, and zombie cursor cleanup. These features share a common base, an idea called a logical session. This new cluster-wide concept of user state is the quiet magic that allows you to know, with certainty, the status of your operations. MongoDB engineer Samantha Ritter will describe the above features in-depth, discuss when and how logical sessions can be used by applications and administrators, and show you how we implemented sessions for large, distributed systems.
What You Will Learn:
- What logical sessions are and how they are implemented in the server
- How to leverage logical sessions for retriable writes
- How to pull the new cluster-wide killOp emergency break
Secure Communications with VisualWorks - CSTUC 2006Martin Kobetic
The document discusses secure communication techniques including:
1) Setting up a certificate authority to issue server and client certificates, and storing certificates and private keys securely on disk.
2) Configuring a secure HTTPS web server using the issued certificates for authentication and encryption.
3) Configuring an HTTPS client to authenticate with the server using the trusted certificate authority and optionally using client certificates for authentication to the server.
4) Considering performance aspects like enabling persistent connections and session resumption to improve efficiency of secure connections.
This document provides information about registering and authenticating with a Touch ID authenticator on a MacBook Pro using the Web Authentication API and FIDO2 standards. It includes code samples and explanations of the registration, attestation, and assertion response objects and flows. Key points covered include how Touch ID returns a packed SELF attestation in the registration response and includes attestedCredentialData in the early Chrome versions, which has since been fixed.
The document contains source code for a client-server chat application written in Java. The client code establishes a socket connection to the server, reads user input and sends messages to the server. The server code initializes a server socket to listen for client connections, spawns a new thread for each client, reads incoming messages and sends responses. The code includes graphical user interface components for selecting the client or server role, composing and displaying messages.
The document discusses building lightweight web APIs with .NET using Nancy. It introduces Nancy and REST concepts like resources, representations, and HTTP verbs. It provides an example of building a RESTful order management API for a coffee shop called Restbucks using Nancy. The API allows clients to place, view, cancel, and pay for orders. Nancy provides a lightweight and readable way to build RESTful services that can be hosted in various environments and is easy to test.
2019-10-05 - Untangled - Voxxed days ticinoArnaud Bos
Concurrent programming borrows a lot of terms from weaving and twists our minds with intertwined concepts: fibers, threads, lightweight-threads, green threads, loom...
Maybe you've heard about coroutines? Don't worry, everything is linked.
During this talk, we'll get weaving, show code samples and talk about project Loom, whose goal is to bring "lightweight concurrency" mechanisms to the JVM, along with APIs to embroider the story.
We will talk about project Loom's inception and recent prototypes. You will also see its mesh goes far beyond "simple" primitives to revolutionize the JVM.
This document describes how to configure Spring Security for authentication and authorization in a web application. It defines a WebSecurityConfig class that configures HTTP security with roles like OWNER and MANAGER for access control. It also defines a UserDetailsManager service for loading users and a User entity class implementing UserDetails. Tests are shown for security configuration, login, access control and more using Spring Security's test utilities.
The document provides an overview of Groovy and Java code examples for performing common tasks like printing "Hello World", reading files, making web requests, using strings, importing packages, and using Swing/SwingBuilder for GUIs. It also shows examples of using Groovy with Java libraries for Excel files, Ant, and JSON. Additional sections cover parallel processing with GPars, contract programming with GContracts, method chaining, Grails basics, and Gaelyk controllers and views.
The document discusses debugging performance problems in MongoDB. It describes solutions tried such as denormalizing data, adding indexes, sharding, scaling hardware, and tagging shards. While performance improved with these solutions at times, slowness still occasionally occurred. The document advocates using monitoring tools like New Relic and Skylight to further analyze issues and find additional solutions.
So you’ve developed an app in MongoDB Stitch? Now what? What is day-to-day use of MongoDB Stitch really like? We’ll talk topics like multi-environment deployment (dev → test → production); logging; testing and timing; and how to best make MongoDB and Stitch work for your application.
It's silly to write the same functionality over and over again. Auth is the most often implemented functionality at web projects. Let's check how can we speed up development by using one of auth provider: Amazon Cognito, Google Firebase or Auth0. On code level we will use custom React Hooks.
The document describes how to create an Android project in Eclipse to call a JSON web service. It includes:
1. Creating a new Android project called "TestJSONWebService" targeting Android 2.2 with an activity called "TestWebServiceActivity" and package name "parallelminds.webservice.com".
2. The main activity, TestWebServiceActivity, makes a call to the web service using the callWebService() method and parses the JSON response to populate a list view.
3. A second class, CallWebService, implements the call to the web service and returns the JSON response.
Securing your Pulsar Cluster with Vault_Chris KelloggStreamNative
Learn how to secure a Pulsar cluster with Hashicorp Vault and deploy it on Kubernetes. Vault provides a secure way to generate tokens and store sensitive data and Pulsar has a pluggable architecture for authentication, authorization and secret management. This talk will walk through how to create custom plugins for Vault, integrate them with Pulsar and then deploy a Pulsar cluster on Kubernetes.
This document discusses client-server connections for a library application. It provides code for a CustomHttpClient class that defines methods for performing HTTP GET and POST requests. This includes setting connection timeout parameters. It also provides code for connecting to a MySQL database and inserting login credentials and book borrowing history. The code samples show how to connect between the client and server and interface with the backend database.
Testdrevet javautvikling på objektorienterte skinnerTruls Jørgensen
The document discusses test-driven development and object-oriented programming principles in Java. It provides examples of using test data builders, object mothers, embedded Jetty servers, JSR 303 validation, and Spring MVC. Additional resources are referenced on testdata builders, object mothers, embedding Jetty, JSR 303, and Spring MVC. The conference JavaZoneX is mentioned.
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?Julian Robichaux
This document discusses Java 8 features like lambdas and streams. It begins with an introduction to lambdas, providing an example of using a lambda expression with the setHostnameVerifier() method instead of an anonymous class. Lambdas allow passing functions as parameters and rely on functional interfaces. The document then covers streams, showing how to iterate over a certificate array using streams instead of a for loop. Additional examples demonstrate sorting a list of sandwiches using different comparator constructions and handling exceptions. The key benefits of lambdas and streams are cleaner, more readable code that encourages a functional programming style.
DEV-1550: Why Java 8? Or, What's a Lambda? – IBM Connect 2017panagenda
When Java 8 hit the streets, a lot of people were either excited or confused about the two biggest language changes that were introduced: lambdas and streams. While these two things might seem to be “just another syntax” for doing what we can already do, it turns out that these two programming techniques are very powerful because of the WAY they work. Even if you’re not using Java 8 just yet, this session will show you the potential of using these new language features.
A presentation by Julian Robichaux (panagenda)
Paco de la Cruz gave a presentation on Durable Functions 2.0 and stateful serverless functions. The presentation covered an overview of serverless computing on Azure, a recap of Azure Functions and an introduction to Durable Functions. It discussed new features in Durable Functions 2.0 including Durable Entities, additional function types and patterns. The presentation also provided demonstrations of common Durable Functions patterns and a stateful serverless request bin application. It concluded with a Q&A section.
The talk presents how we established a TDD cycle within the complex AEM technology stack using a "unified testing API". It illustrates how such an API can be built and discusses various advantages over other approaches such as the Sling Testing API.
The document discusses test-driven development (TDD). It states that TDD relies on short development cycles where the developer first writes an automated test case that defines a new function or improvement. Then the developer produces code to pass that test, and refactors the new code to acceptable standards.
The OWASP Proxy is an intercepting proxy library that allows visibility and modification of HTTP communications in a flexible, performant way. It provides a message object model that allows buffering or streaming of requests and responses. The proxy can be used to implement useful functions like response inspection, reverse proxying, and integration with technologies like SSL, SOCKS, and Apache JServ Protocol. It aims to be a clean, multi-protocol foundation for building custom proxies.
Viele performante und gut skalierbare Architekturen setzen auf asynchrone Verarbeitung. Das Testen des asynchronen Codes stellt Entwickler allerdings vor neue Herausforderungen. Dieser Vortrag bietet Orientierung für einige typischen Fragestellungen. Am Beispiel von NodeJS und Mocha wird gezeigt, wie das Testen beim Einsatz einer nicht-blockierenden Event Loop funktioniert. Anschließend illustriert der Vortrag, wie asynchroner Code mit JUnit auf der JVM – einer klassischen Multithreading-Plattform – getestet werden kann. Insbesondere wird darauf eingegangen, welche Synchronisationsmechanismen genutzt werden können und wie Race Conditions durch Unit Tests aufgedeckt werden können.
Code unter: https://github.com/andreassimon/talk-asynchronen-code-testen
The document discusses new features in Swift 2.0 including checking API availability, synthesized headers, protocol extensions, error handling improvements, and more. It provides code examples for checking API availability using #available, generating synthesized headers, using protocol extensions to provide default implementations, and the new try/catch syntax for error handling.
Sample JavaScript Code Laurence Svekis
JavaScript Closure
A closure in JavaScript is a function that has access to the variables in its parent scope, even after the parent function has completed execution. This allows for data to be “closed over” or remembered by the inner function, even after the outer function has returned.
Here, the makeCounter function returns an inner function that has access to the count variable declared in its parent scope, and can “remember” the current count value even after the makeCounter function has completed execution. Each time the inner function is called, it returns the current value of count and increments it by 1.
JavaScript Closure Advanced
In this example, the makeAdder function takes in a single argument x and returns an inner function that takes in a second argument y. The inner function has access to the x variable declared in the parent scope and uses it to add x and y together and return the result.
We can see here that the outer function makeAdder has been executed twice and it returns two different inner functions which are assigned to different variables add5 and add10 and these inner functions are able to remember their respective parent scope values of x.
This document discusses using Netty for building high performance reactive servers. It provides an overview of Netty's features such as non-blocking I/O, channel pipelines, event loops and performance optimizations. Examples are given of building HTTP and TCP servers using Netty. Reasons for choosing Netty include its high performance, low garbage collection overhead, support for various protocols and full control over networking.
CIS14: Developing with OAuth and OIDC ConnectCloudIDSummit
David Chase, Ping Identity
Exploring the implementation and architecture of OAuth and OpenID Connect, using web and mobile applications, with topics including grant types, choosing a grant type, refresh tokens, and managing sessions
Video and slides synchronized, mp3 and slide download available at URL http://bit.ly/254wkpw.
Aaron Bedra focuses on describing a system as a series of models that can be used to systematically and automatically generate input data and ensure that a code is behaving as expected. Bedra discusses property based testing and how it can help one build more resilient systems and even reduce the time needed to maintain a test suite. Filmed at qconlondon.com.
Aaron Bedra is Chief Security Officer at eligible.com. He is the creator of Repsheet, an open source threat intelligence framework. Bedra is the co-author of Programming Clojure, 2nd Edition and a frequent contributor to open source software.
This document summarizes Paco de la Cruz's presentation on Azure Durable Functions. The presentation covered the evolution of application platforms from on-premises to serverless. It then discussed Azure Functions and some challenges it faces with stateful orchestrations. Durable Functions were introduced as an extension of Azure Functions that uses a Durable Task Framework to implement stateful workflows in a serverless manner. Key patterns demonstrated include function chaining, fan-out/fan-in, and using an orchestration client to start and monitor orchestrations. Code samples and demos were provided to illustrate approval workflows using Durable Functions.
Web CrawlersrcedusmulylecrawlerController.javaWeb Crawler.docxcelenarouzie
Web Crawler/src/edu/smu/lyle/crawler/Controller.javaWeb Crawler/src/edu/smu/lyle/crawler/Controller.javapackage edu.smu.lyle.crawler;
publicclassController{
publicstaticvoid main(String[] args)throwsException{
String crawlStorageFolder ="/data/crawl/root";
int numberOfCrawlers =1;
CrawlConfig config =newCrawlConfig();
config.setCrawlStorageFolder(crawlStorageFolder);
/*
* Instantiate the controller for this crawl.
*/
PageFetcher pageFetcher =newPageFetcher(config);
RobotstxtConfig robotstxtConfig =newRobotstxtConfig();
RobotstxtServer robotstxtServer =newRobotstxtServer(robotstxtConfig, pageFetcher);
CrawlController controller =newCrawlController(config, pageFetcher, robotstxtServer);
/*
* For each crawl, you need to add some seed urls. These are the first
* URLs that are fetched and then the crawler starts following links
* which are found in these pages
*/
controller.addSeed("http://www.lyle.smu.edu/~fmoore/");
/*
* Start the crawl. This is a blocking operation, meaning that your code
* will reach the line after this only when crawling is finished.
*/
controller.start(MyCrawler.class, numberOfCrawlers);
}
}
Web Crawler/src/edu/smu/lyle/crawler/Main.javaWeb Crawler/src/edu/smu/lyle/crawler/Main.javapackage edu.smu.lyle.crawler;
import java.nio.channels.Pipe;
import java.util.regex.Pattern;
publicclassMain<WebURL>{
privatefinalstaticPattern FILTERS =Pattern.compile(".*(\\.(css|js|gif|jpg"
+"|png|mp3|mp3|zip|gz))$");
/**
* This method receives two parameters. The first parameter is the page
* in which we have discovered this new url and the second parameter is
* the new url. You should implement this function to specify whether
* the given url should be crawled or not (based on your crawling logic).
* In this example, we are instructing the crawler to ignore urls that
* have css, js, git, ... extensions and to only accept urls that start
* with "http://www.lyle.smu.edu~fmoore/". In this case, we didn't need the
* referringPage parameter to make the decision.
*/
publicboolean shouldVisit(Package referringPage,WebURL url){
String href =((Object) url).getURL().toLowerCase();
return!FILTERS.matcher(href).matches()
&& href.startsWith("http://www.lyle.smu.edu~fmoore/");
}
/**
* This function is called when a page is fetched and ready
* to be processed by your program.
*/
publicvoid visit(Pipe page){
String url =((Object) page)).getWebURL().getURL();
System.out.println("URL: "+ url);
if(page.getParseData()instanceofHtmlParseData){
HtmlParseData htmlParseData =(HtmlParseData) page.getParseData();
String text = htmlParseData.getText();
String html = htmlParseData.getHtml();
Set<WebURL> links = htmlParseData.getOutgoingUrls();
System.out.println("Text length: "+ text.length());
System.out.println("Html length: "+ html.length());
System.out.println("Number of outgoing links: "+ links.size.
2. JSONParser
Para recoger datos de una pagina https sin comprobar el certificado desde el JSON hay que
hacer lo siguiente.
2.1 Imports
Primeramente crearemos una clase que se va a llamar JSONParser que hará la llamada al
sitio web y recogerá los datos del JSON. Empezara con los imports de la siguiente manera:
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
2.2 Clase
Y ahora si empezamos la clase inicializando las variables que necesitamos:
public class JSONParser {
static JSONObject jObj = null;
static String json = "";
String responseJsonData = null;
HttpURLConnection conn = null;
Ahora creamos el constructor:
public JSONParser() {
}
Lo siguiente que haremos sera empezar la verificacion del sitio web:
final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session){
return true;
}
};
Ahora crearemos la funcion para aceptar todos los verificados:
private static void trustAllHosts(){
3. TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers(){
return new java.security.cert.X509Certificate[] {};
}
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
}
};
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
e.printStackTrace();
}
}
Bien, ya tenemos las funciones de como verificar el sitio web y de aceptar todos los
certificados, ahora nos queda hacer la conexión. Desde la clase que llama a JSONParser le
pasamos la URL y el método (GET, PUT, POST, etc...) así que sabiendo esto empezamos la
función:
public JSONObject makeHttpRequest(String url, String method) {
try {
URL url1 = new URL(url);
Ahora comprobaremos si tiene protocolo https o no y si lo tiene verificaremos el sitio y aceptaremos
todos los certifiados y si no haremos una conexión normal sin comprobaciones:
if (url1.getProtocol().toLowerCase().equals("https")) {
trustAllHosts();
HttpsURLConnection https = (HttpsURLConnection) url1.openConnection();
https.setHostnameVerifier(DO_NOT_VERIFY);
conn = https;
} else {
conn = (HttpURLConnection) url1.openConnection();
}
conn.setRequestMethod(method);
Una vez hecha la conexión descargamos los datos del JSON:
System.out.println("Response Code: " + conn.getResponseCode());
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
if(in !=null) {
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = in.readLine()) != null) {
sb.append(line + "n");
}
in.close();
json = sb.toString();
}
responseJsonData = new String(json);
Una vez descargados terminamos las excepciones y metemos los datos en un JSONObject:
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
5. }
}
public JSONObject makeHttpRequest(String url, String method) {
try {
URL url1 = new URL(url);
if (url1.getProtocol().toLowerCase().equals("https")) {
trustAllHosts();
HttpsURLConnection https = (HttpsURLConnection) url1.openConnection();
https.setHostnameVerifier(DO_NOT_VERIFY);
conn = https;
} else {
conn = (HttpURLConnection) url1.openConnection();
}
conn.setRequestMethod(method);
System.out.println("Response Code: " + conn.getResponseCode());
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
if(in !=null) {
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = in.readLine()) != null) {
sb.append(line + "n");
}
in.close();
json = sb.toString();
}
responseJsonData = new String(json);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
return jObj;
}
}
OrdersActivity
Y ya tenemos el JSONParser hecho, ahora nos queda como hacer la llamada y como recoger
los datos para meterlos en una DB y de ahí sacarlos en una lista para después ponerlo en
pantalla.
3.1 Activity
Dicho esto creamos una activity nueva que tendrá una lista y un botón de actualizar los datos
del JSON:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
8. 3.2 Clase
Una vez hecha ya la activity procederemos a configurar el codigo.
3.2.1 Imports
Primero, como no, empezaremos con los imports que vamos a necesitar:
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.os.AsyncTask;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.urlanheat.abacowarehouse.util.DBAbaco;
import com.urlanheat.abacowarehouse.util.JSONParser;
import com.urlanheat.abacowarehouse.util.Order;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
3.2.2 Clase
Empezamos la clase inicializando las variables:
public class OrdersActivity extends ActionBarActivity {
private List<Order> ordersList = new ArrayList<Order>();
int orderType = 0;
String myUrl = "https://******************************";
JSONParser jParser = new JSONParser();
JSONArray reservation = null;
JSONArray listing = null;
Button btnUpdate;
DBAbaco db;
Ahora haremos el onCreate que preparara el botón de actualizar para sacar la lista de
9. pedidos de la DB:
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_order);
db = new DBAbaco(this);
db.open();
Bundle b = getIntent().getExtras();
orderType = Integer.parseInt((String) b.getCharSequence("listingType"));
setupUpdateButton();
}
A continuación tenemos las opciones por defecto al crear una activity que no tocaremos:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this addsitems to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_pedidos, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clickshere. The action bar will
// automatically handle clickson 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.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
Llamaremos a la funcion setupUpdateButton() que tendrá el siguiente código:
private void setupUpdateButton(){
btnUpdate = (Button) findViewById(R.id.updateButton);
btnUpdate.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
new LoadAllOrders().execute();
}
});
}
3.2.3 JSON
Esta función prepara el botón para que al hacer un click en el cargue los datos del JSON a la
DB. Al no saber cuento puede durar la descarga y para que el sistema no nos cierre el proceso
lo haremos en una tarea Asíncrona, es decir, en segundo plano. Como es otra clase dentro de
10. la misma clase tendremos que inicializar las variables que utilizaremos en esta tarea:
class LoadAllOrders extends AsyncTask<String, String, String> {
private ProgressDialog progressDialog = new ProgressDialog(OrdersActivity.this);
long orderID = 0;
int status = 0;
long clientID = 0;
String clientName = "";
long detailID = 0;
int equipmentTypeID = 0;
String equipmentID = "";
Esta tarea en segundo plano lleva funciones opcionales, nosotros aprovecharemos algunas:
protected void onPreExecute() {
progressDialog.setMessage("Descargando pedidos...");
progressDialog.show();
progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface arg0) {
LoadAllOrders.this.cancel(true);
}
});
}
Con esta función lo que haremos sera poner un cuadro de dialogo de cargando mientras se
descargan los datos del JSON. Ahora pondremos la función que hace la llamada al
JSONParser y recoge los datos en variables para meterlos en la DB, para ello le pasaremos la
URL que hemos puesto al principio del código y limpiaremos las listas y las tablas:
@Override
protected String doInBackground(String... params) {
String url_select = myUrl;
ordersList.clear();
db.dropTables();
db.createTables();
Las funciones que veis aquí las explicaremos mas adelante cuando creemos la clase de la DB.
Ahora empezaremos con la llamada al JSONParser:
try {
JSONObject json = jParser.makeHttpRequest(url_select, "GET");
Aqui hacemos la llamada al JSONParser y como hemos dicho en la clase del JSONParser,
aquí le mandamos la URL y el metodo, en nuestro caso el GET. Ahora dejo una imagen de
como se trata la estructura del JSON:
11. Primeramente, el nombre de JSON no se coge, digamos que es el inicial.
Se empezaría por pedidos, así que para “seleccionar” seria de la siguiente manera:
JSONObject orders = json.getJSONObject("pedidos");
El item siguiente seria reservas, que como esta entre corchetes([]) seria una array, en este caso
solo tendría un item, el código es el siguiente:
reservation = orders.getJSONArray("reservas");
Ahora tenemos que recorrer el array:
for (int reservationNumber = 0; reservationNumber < reservation.length(); reservationNumber++){
Ahora una vez empezado a recorrer el array, tenemos que selecciona la posicion, en nuestro
aso seria el 0:
JSONObject jsonObjOrders = reservation.getJSONObject(reservationNumber);
Teniendo la posición, procedemos a coger los items del array:
orderID = jsonObjOrders.getLong("id_reserva");
status = jsonObjOrders.getInt("estado");
clientID = jsonObjOrders.getLong("id_cliente");
clientName = jsonObjOrders.getString("nombre");
Ahora vemos que nos llega otra subclase, pues bien hacemos como antes, “seleccionaremos” el
item:
JSONObject equipment = jsonObjOrders.getJSONObject("equipos");
Ya tenemos el item seleccionado, ahora cojeremos el array:
listing = equipment.getJSONArray("listado");
Ahora nos recorreremos el array:
for (int equipmentNumber = 0; equipmentNumber < listing.length(); equipmentNumber++){
Nos recorremos el array:
JSONObject jsonObjEquipment = listing.getJSONObject(equipmentNumber);
Cogemos los items del nuevo array:
detailID = jsonObjEquipment.getLong("id_detalle_reserva");
equipmentTypeID = jsonObjEquipment.getInt("tipo_producto");
12. equipmentID = jsonObjEquipment.getString("id_equipo");
A continuación como ya tenemos todos los items del array los guardamos en ls DB que
posteriormente explicaremos la función:
db.insertEquipment(detailID, equipmentTypeID, equipmentID, orderID);
}
Una vez insertado en la base de datos del segundo array, ahora procederemos a insertar el
primer array en la DB:
db.insertOrder(orderID, status, clientID, clientName);
}
y para acabar la funcion pondremos las excepciones:
}catch(IllegalStateException e3){
Log.e("IllegalStateException", e3.toString());
e3.printStackTrace();
}catch(JSONException e5){
Log.e("JSONException", e5.toString());
e5.printStackTrace();
}
return null;
}
Ahora agregaremos otra función para que cuando finalice la función principal haga lo que le
digamos, la función es la siguiente:
@Override
protected void onPostExecute(String s) {
try {
new AccesoDB().execute();
progressDialog.dismiss();
} catch (Exception e) {
Log.e("JSONException", "Error: " + e.toString());
}
}
}
3.2.4 AcesoDB
En esta función lo que hacemos es pasar a otra tarea en segundo plano para sacar lo que
tenemos guardado y meterlo en una lista. La mecánica de la clase es la misma, primero
inicializar las variables:
public class AccesoDB extends AsyncTask<Object, Integer, Boolean> {
private ProgressDialog progressDialog = new ProgressDialog(OrdersActivity.this);
Ahora haremos la función que hace que salga un cuadro de dialogo con la descripción de
cargando:
protected void onPreExecute() {
progressDialog.setMessage("Descargando pedidos...");
progressDialog.show();
progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface arg0) {
AccesoDB.this.cancel(true);
}
13. });
}
Después iremos con la función principal que nos descargara los datos de la DB a la lista:
@Override
protected Boolean doInBackground(Object... params) {
ordersList.clear();
Cursor cursor= db.getOrderListing(orderType);
if (cursor.moveToFirst()) {
do {
long orderID = cursor.getLong(DBAbaco.COL_ORDER_ID);
ordersList.add(new Order(orderID));
} while (cursor.moveToNext());
}
return null;
}
Y para acabar haremos la ultima función que se hará cuando acabe la función principal:
@Override
protected void onPostExecute(Boolean s) {
setupOrdersListView();
registerClickCallback();
progressDialog.dismiss();
}
}
3.2.5 Lista
Esta función llama a otras funciones que no estánen la tarea en segundo plano ya que no
cargan mucho, por eso las colocaremos mas arriba (Cuando acabe os pondré el código
entero). La función seria la siguiente:
private void setupOrdersListView() {
orderListAdapter adapter = new orderListAdapter(this, ordersList);
ListView lvOrders = (ListView) findViewById(R.id.ordersListing);
lvOrders.setAdapter(adapter);
}
Esta función cargara la lista en la pantalla mediante un adapter:
private class orderListAdapter extends ArrayAdapter<Order> {
public orderListAdapter(Context context, List<Order> orders) {
super(context, 0, orders);
}
@Override
public View getView(int position,View convertView, ViewGroup parent) {
View orderView = convertView;
if (orderView==null) {
orderView = getLayoutInflater().inflate(R.layout.user_button, parent, false);
14. }
Order currentOrder = ordersList.get(position);
TextView orderID = (TextView) orderView.findViewById(R.id.user_name);
orderID.setText(String.valueOf(currentOrder.getOrderID()));
return orderView;
}
}
Una vez cargada la lista y los items se muestren en la pantalla la siguiente función registrara
el poder clickear los items de la lista. Llamaremos a la función e inicializaremos la lista:
private void registerClickCallback() {
ListView list = (ListView) findViewById(R.id.ordersListing);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
Order selectedOrder;
Ahora haremos la propiedad del click de la lista:
@Override
public void onItemClick(AdapterView<?> parent, View viewClicked, int position, long id) {
getSelectedOrderFromList(position);
displayOrderSelectedMessage();
showOrderDetailList();
}
Dentro de esta propiedad tenemos 3 funciones, la primera seleccionara el item de la lista que
hemos elegido:
private void getSelectedOrderFromList(int position) {
selectedOrder = ordersList.get(position);
}
La segunda función pondrá un texto en la parte inferior de la pantalla para decir que hemos
seleccionado el item:
private void displayOrderSelectedMessage() {
String message = String.format(getString(R.string.abc_selected_pedido), selectedOrder.getOrderID());
Toast.makeText(OrdersActivity.this,message, Toast.LENGTH_SHORT).show();
}
Y en la ultima funcion hara la llamada a otra actividad:
private void showOrderDetailList() {
Intent intent = new Intent(OrdersActivity.this, OrderDetailActivity.class);
Bundle b = new Bundle();
b.putString("orderID", String.valueOf(selectedOrder.getOrderID()));
b.putString("orderType", String.valueOf(orderType));
intent.putExtras(b);
startActivity(intent);
}
});
}
15. 3.2.6 Codigo
Habriamos terminado de programar la clase de la actividad que muestra la lista, el código
completo y sin interrupciones seria el siguiente:
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.os.AsyncTask;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.urlanheat.abacowarehouse.util.DBAbaco;
import com.urlanheat.abacowarehouse.util.JSONParser;
import com.urlanheat.abacowarehouse.util.Order;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class OrdersActivity extends ActionBarActivity {
private List<Order> ordersList = new ArrayList<Order>();
int orderType = 0;
String myUrl = "https://******************************";
JSONParser jParser = new JSONParser();
JSONArray reservation = null;
JSONArray listing = null;
Button btnUpdate;
DBAbaco db;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_order);
db = new DBAbaco(this);
db.open();
Bundle b = getIntent().getExtras();
orderType = Integer.parseInt((String) b.getCharSequence("listingType"));
setupUpdateButton();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this addsitems to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_pedidos, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clickshere. The action bar will
// automatically handle clickson the Home/Up button,so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
16. //noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private void setupUpdateButton(){
btnUpdate = (Button) findViewById(R.id.updateButton);
btnUpdate.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
new LoadAllOrders().execute();
}
});
}
private void setupOrdersListView() {
orderListAdapter adapter = new orderListAdapter(this, ordersList);
ListView lvOrders = (ListView) findViewById(R.id.ordersListing);
lvOrders.setAdapter(adapter);
}
private void registerClickCallback() {
ListView list = (ListView) findViewById(R.id.ordersListing);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
Order selectedOrder;
@Override
public void onItemClick(AdapterView<?> parent, View viewClicked, int position, long id) {
getSelectedOrderFromList(position);
displayOrderSelectedMessage();
showOrderDetailList();
}
private void getSelectedOrderFromList(int position){
selectedOrder = ordersList.get(position);
}
private void displayOrderSelectedMessage() {
String message = String.format(getString(R.string.abc_selected_pedido),
selectedOrder.getOrderID());
Toast.makeText(OrdersActivity.this,message, Toast.LENGTH_SHORT).show();
}
private void showOrderDetailList() {
Intent intent = new Intent(OrdersActivity.this, OrderDetailActivity.class);
Bundle b = new Bundle();
b.putString("orderID", String.valueOf(selectedOrder.getOrderID()));
b.putString("orderType", String.valueOf(orderType));
intent.putExtras(b);
startActivity(intent);
}
});
}
private class orderListAdapter extends ArrayAdapter<Order> {
public orderListAdapter(Context context, List<Order> orders) {
super(context, 0, orders);
}
@Override
public View getView(int position,View convertView, ViewGroup parent) {
View orderView = convertView;
if (orderView==null) {
orderView = getLayoutInflater().inflate(R.layout.user_button, parent, false);
}
Order currentOrder = ordersList.get(position);
TextView orderID = (TextView) orderView.findViewById(R.id.user_name);
orderID.setText(String.valueOf(currentOrder.getOrderID()));
return orderView;
}
17. }
public class AccesoDB extends AsyncTask<Object, Integer, Boolean> {
private ProgressDialog progressDialog = new ProgressDialog(OrdersActivity.this);
protected void onPreExecute() {
progressDialog.setMessage("Descargando pedidos...");
progressDialog.show();
progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface arg0) {
AccesoDB.this.cancel(true);
}
});
}
@Override
protected Boolean doInBackground(Object... params) {
ordersList.clear();
Cursor cursor= db.getOrderListing(orderType);
if (cursor.moveToFirst()) {
do {
long orderID = cursor.getLong(DBAbaco.COL_ORDER_ID);
ordersList.add(new Order(orderID));
} while (cursor.moveToNext());
}
return null;
}
@Override
protected void onPostExecute(Boolean s) {
setupOrdersListView();
registerClickCallback();
progressDialog.dismiss();
}
}
class LoadAllOrders extends AsyncTask<String, String, String> {
private ProgressDialog progressDialog = new ProgressDialog(OrdersActivity.this);
long orderID = 0;
int status = 0;
long clientID = 0;
String clientName = "";
long detailID = 0;
int equipmentTypeID = 0;
String equipmentID = "";
protected void onPreExecute() {
progressDialog.setMessage("Descargando pedidos...");
progressDialog.show();
progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface arg0) {
LoadAllOrders.this.cancel(true);
}
});
}
@Override
protected String doInBackground(String... params) {
String url_select = myUrl;
ordersList.clear();
db.dropTables();
db.createTables();
try {
JSONObject json = jParser.makeHttpRequest(url_select, "GET");
Log.d("All Products: ", json.toString());
JSONObject orders = json.getJSONObject("pedidos");
reservation = orders.getJSONArray("reservas");
for (int reservationNumber = 0; reservationNumber < reservation.length();
reservationNumber++){
JSONObject jsonObjOrders = reservation.getJSONObject(reservationNumber);
18. orderID = jsonObjOrders.getLong("id_reserva");
status = jsonObjOrders.getInt("estado");
clientID = jsonObjOrders.getLong("id_cliente");
clientName = jsonObjOrders.getString("nombre");
JSONObject equipment = jsonObjOrders.getJSONObject("equipos");
listing = equipment.getJSONArray("listado");
for (int equipmentNumber = 0; equipmentNumber < listing.length();
equipmentNumber++){
JSONObject jsonObjEquipment = listing.getJSONObject(equipmentNumber);
detailID = jsonObjEquipment.getLong("id_detalle_reserva");
equipmentTypeID = jsonObjEquipment.getInt("tipo_producto");
equipmentID = jsonObjEquipment.getString("id_equipo");
db.insertEquipment(detailID, equipmentTypeID, equipmentID, orderID);
}
db.insertOrder(orderID, status, clientID, clientName);
}
}catch(IllegalStateException e3){
Log.e("IllegalStateException", e3.toString());
e3.printStackTrace();
}catch(JSONException e5){
Log.e("JSONException", e5.toString());
e5.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String s) {
try {
new AccesoDB().execute();
progressDialog.dismiss();
} catch (Exception e) {
Log.e("JSONException", "Error: " + e.toString());
}
}
}
}
User_button
Bien, en este punto nos saldrá algún error, ya que faltan clases y una activity.
4.1 Activity
la activity que falta que es la activity user_button que necesita el adapter para poder hacer la
lista es la siguiente:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="@+id/user_name"
android:textSize="30sp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:layout_gravity="center_horizontal" />
19. </LinearLayout>
Con este código nos saldrá la siguiente apariencia:
Order
Ahora crearemos la clase Order para hacer la lista, en este caso no necesitamos imports, por
lo que empezamos directamente con la clase e inicializando las variables:
public class Order {
long orderID = 0;
int status = 0;
long clientID = 0;
String clientName = "";
long detailID = 0;
int equipmentTypeID = 0;
String equipmentID = "";
20. Ahora empezaremos con las funciones, lo primero que tenemos que hacer es el constructor:
public Order(long detailID, int equipmentTypeID, String equipmentID, long orderID){
this.detailID = detailID;
this.equipmentTypeID = equipmentTypeID;
this.equipmentID = equipmentID;
this.orderID = orderID;
}
Y seguiremos con las funciones que necesitamos para llamar a cada uno de los items de la lista
(Estas funciones las vamos creando segúnnecesidad):
public Order (long orderID){
this.orderID = orderID;
}
public long getOrderID() {
return orderID;
}
public String getEquipmentID(){
return equipmentID;
}
public int getEquipmentType(){
return equipmentTypeID;
}
public long getEquipmentDetail() {
return detailID;
}
}
Si os habéis fijado tenemos dos constructores, se pueden hacer varias funciones con el mismo
nombre. Ahora el código completo de la clase Orders:
public class Order {
long orderID = 0;
int status = 0;
long clientID = 0;
String clientName = "";
long detailID = 0;
int equipmentTypeID = 0;
String equipmentID = "";
public Order(long detailID, int equipmentTypeID, String equipmentID, long orderID){
this.detailID = detailID;
this.equipmentTypeID = equipmentTypeID;
this.equipmentID = equipmentID;
this.orderID = orderID;
}
public Order (long orderID){
this.orderID = orderID;
}
public long getOrderID() {
return orderID;
}
public String getEquipmentID(){
return equipmentID;
}
public int getEquipmentType(){
return equipmentTypeID;
}
public long getEquipmentDetail() {
return detailID;
21. }
}
DBAbaco
Ahora veremos el codigo de la base de datos DBAbaco.
6.1 Imports
Lo primero es hacer los imports:
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
6.2 Clase
Inicializamos la clase y las variables necesarias para crear una Base de Datos:
private static final String TAG = "DBAbaco";
public static final String DATABASE_NAME = "AbacoUser";
public static final int DATABASE_VERSION = 36;
public static final String KEY_USER_NAME = "nombre_usuario";
public static final String KEY_USER_PASSWORD = "contraseña_usuario";
public static final String KEY_ORDER_ID = "id_pedido";
public static final String KEY_ORDER_STATUS = "estado";
public static final String KEY_ORDER_STATUS_WORD = "significado";
public static final String KEY_CLIENT_ID = "id_cliente";
public static final String KEY_DETAIL_EQUIPMENT_ID = "id_detalle";
public static final String KEY_EQUIPMENT_ID = "id_equipo";
public static final String KEY_EQUIPMENT_CATEGORY = "categoria_equipo";
public static final String KEY_EQUIPMENT_DESCRIPTION = "descripcion_equipo";
public static final String KEY_CLIENT_NAME = "nombre";
public static final String KEY_COMPONENT = "componente";
public static final String KEY_COMPONENT_SENT = "componente_enviado";
public static final String KEY_COMPONENT_RETURN = "componente_devuelto";
public static final String KEY_EQUIPMENT_GAMMA = "Gamma";
public static final String KEY_DETAIL_ORDER_ID = "id_detalle_pedido";
public static final String TABLE_USER = "Usuarios";
public static final String TABLE_ORDER_STATUS = "Estado ordenes";
public static final String TABLE_ORDER = "Pedidos";
public static final String TABLE_EQUIPMENT = "Equipos";
public static final String TABLE_COMPONENT = "Componentes";
public static final String TABLE_DETAIL_ORDER = "OrderDetail";
private static final String CREATE_TABLE_USER =
"CREATE TABLE IF NOT EXISTS " + TABLE_USER
+ " (" + KEY_USER_NAME + " text not null, "
+ KEY_USER_PASSWORD + " int(4) not null "
+ ");";
private static final String CREATE_TABLE_ORDER_STATUS =
"CREATE TABLE IF NOT EXISTS " + TABLE_ORDER_STATUS
22. + " (" + KEY_ORDER_STATUS + " int PRIMARY KEY, "
+ KEY_ORDER_STATUS_WORD + " text not null "
+ ");";
private static final String CREATE_TABLE_ORDER =
"CREATE TABLE IF NOT EXISTS " + TABLE_ORDER
+ " (" + KEY_ORDER_ID + " REAL PRIMARY KEY, "
+ KEY_ORDER_STATUS + " int not null, "
+ KEY_CLIENT_ID + " REAL not null, "
+ KEY_CLIENT_NAME + " NVARCHAR(100) not null "
+ "FOREIGN KEY(" + KEY_ORDER_STATUS + ") REFERENCES " +
TABLE_ORDER_STATUS + "(" + KEY_ORDER_STATUS
+ "));";
private static final String CREATE_TABLE_EQUIPMENT =
"CREATE TABLE IF NOT EXISTS " + TABLE_EQUIPMENT
+ " (" + KEY_DETAIL_EQUIPMENT_ID + " REAL not null, "
+ KEY_EQUIPMENT_CATEGORY + " text not null, "
+ KEY_EQUIPMENT_ID + " INT not null, "
+ KEY_ORDER_ID + " REAL not null, "
+ "FOREIGN KEY(" + KEY_ORDER_ID + ") REFERENCES " + TABLE_ORDER + "("
+ KEY_ORDER_ID
+ "));";
private static final String CREATE_TABLE_COMPONENT =
"CREATE TABLE IF NOT EXISTS " + TABLE_COMPONENT
+ " (" + KEY_DETAIL_EQUIPMENT_ID + " text not null, "
+ KEY_COMPONENT + " text not null, "
+ KEY_COMPONENT_SENT + " text not null, "
+ KEY_COMPONENT_RETURN + " text not null, "
+ "FOREIGN KEY(" + KEY_DETAIL_EQUIPMENT_ID + ") REFERENCES " +
TABLE_EQUIPMENT + "(" + KEY_DETAIL_EQUIPMENT_ID
+ "));";
private static final String CREATE_TABLE_ORDER_DETAIL =
"CREATE TABLE IF NOT EXISTS " + TABLE_DETAIL_ORDER
+ " (" + KEY_ORDER_ID + " int not null, "
+ KEY_DETAIL_EQUIPMENT_ID + " text not null, "
+ "FOREIGN KEY(" + KEY_ORDER_ID + ") REFERENCES " + TABLE_ORDER + "("
+ KEY_ORDER_ID + "), "
+ "FOREIGN KEY(" + KEY_DETAIL_EQUIPMENT_ID + ") REFERENCES " +
TABLE_EQUIPMENT + "(" + KEY_DETAIL_EQUIPMENT_ID
+ "));";
public static final int COL_USER = 0;
public static final int COL_ORDER_ID = 0;
public static final int COL_EQUIPMENT_DETAIL_ID = 0;
public static final int COL_EQUIPMENT_CATEGORY = 1;
public static final int COL_EQUIPMENT_ID = 2;
public static final int COL_EQUIPMENT_ORDER_ID = 3;
public static final int COL_ORDER_DETAIL_ID = 0;
public static final int COL_ORDER_DETAIL_EQUIPMENT_ID = 1;
public static int ORDER_TYPE_OUTGOING = 1;
public static int ORDER_TYPE_INCOMING = 2;
public final Context context;
private DatabaseHelper myDBHelper;
protected SQLiteDatabase db;
Si os fijais, la tercera variable es la versión de la base de datos, cambiando esta versión rehace
la base de datos entera, ahora viene la funcion del context:
public DBAbaco(Context ctx) {
this.context = ctx;
myDBHelper = new DatabaseHelper(context);
}
La siguiente funcion sirve para abrir la Base de Datos:
public DBAbaco open() {
23. db = myDBHelper.getWritableDatabase();
return this;
}
Y ahora toca cerrarla:
public void close() {
myDBHelper.close();
}
Lo siguiente es crear una clase para la Base de datos:
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
6.3 Creacion de la DB
Ahora iremos al onCreate de esta función que es donde crearemos las tablas y crearemos
registros por defecto en las tablas:
@Override
public void onCreate(SQLiteDatabase _db) {
_db.execSQL(CREATE_TABLE_USER);
_db.execSQL(CREATE_TABLE_ORDER_STATUS);
_db.execSQL(CREATE_TABLE_ORDER);
_db.execSQL(CREATE_TABLE_EQUIPMENT);
_db.execSQL(CREATE_TABLE_COMPONENT);
_db.execSQL(CREATE_TABLE_ORDER_DETAIL);
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_USER + " (" + KEY_USER_NAME + ", " +
KEY_USER_PASSWORD + ") VALUES ('GORKA', 1234)");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_USER + " (" + KEY_USER_NAME + ", " +
KEY_USER_PASSWORD + ") VALUES ('IRATXE', 1234)");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_USER + " (" + KEY_USER_NAME + ", " +
KEY_USER_PASSWORD + ") VALUES ('INMA', 1234)");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_USER + " (" + KEY_USER_NAME + ", " +
KEY_USER_PASSWORD + ") VALUES ('RAUL', 1234)");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (0, 'Presupuesto')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (2, 'Confirmado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (3, 'Pagado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (4, 'Enviado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (6, 'Devuelto')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (7, 'Recoger')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (8, 'Fianza devuelta')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (9, 'Comprobado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (10, 'Envio solicitado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (11, 'Devolucion solicitada')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (12, 'Recogido en local')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (14, 'Presupuesto')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
24. KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (15, 'Confirmado local')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (16, 'Cancelado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (17, 'Devuelto local')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (18, 'Uso en local')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (20, 'Email enviado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (21, 'Preparado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (22, 'Cancelado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (23, 'Contrato aceptado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (24, 'Contrato desmarcado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (25, 'Fianza NO devuelta')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (26, 'Devuelto, falta material')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (27, 'Envio fallido')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (28, 'Continua en otra
reserva')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (29, 'Ampliacion reserva')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (30, 'Solicitados comentarios')");
}
Otra función que te crea la clase es la siguiente, que en caso de cambiar de versión rehace la
base de datos:
@Override
public void onUpgrade(SQLiteDatabase _db, int oldVersion, int newVersion) {
_db.execSQL("DROP TABLE IF EXISTS " + TABLE_USER);
_db.execSQL("DROP TABLE IF EXISTS " + TABLE_ORDER);
_db.execSQL("DROP TABLE IF EXISTS " + TABLE_EQUIPMENT);
_db.execSQL("DROP TABLE IF EXISTS " + TABLE_COMPONENT);
_db.execSQL("DROP TABLE IF EXISTS " + TABLE_DETAIL_ORDER);
onCreate(_db);
}
}
6.4 Funciones
Y aquí acaba la clase de la base de datos. Como os dije antes, aquí están algunas llamadas que
se hacen para insertar o consultar en la base de datos, o simplemente rehacer las tablas que
necesitamos. En este caso llamamos a dos funciones para rehacer la base de datos:
public void dropTables(){
db.execSQL("DROP TABLE IF EXISTS " + TABLE_ORDER);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_EQUIPMENT);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_COMPONENT);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_DETAIL_ORDER);
}
public void createTables(){
db.execSQL(CREATE_TABLE_ORDER);
25. db.execSQL(CREATE_TABLE_EQUIPMENT);
db.execSQL(CREATE_TABLE_COMPONENT);
db.execSQL(CREATE_TABLE_ORDER_DETAIL);
}
Las siguientes funciones las utilizamos en el JSON para insertar registros en la base de datos,
la primera la usaremos para insertar los pedidos en la tabla de pedidos:
public void insertOrder(long orderID, int status,long clientID, String clientName){
db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER + " (" + KEY_ORDER_ID + ", " +
KEY_ORDER_STATUS + ", " + KEY_CLIENT_ID + ", " + KEY_CLIENT_NAME + ") VALUES (" + orderID +
", " + status +", " + clientID + ", '" + clientName + "')");
}
La segunda funcion la usaremos para insertar los equipos en la tabla de equipos:
public void insertEquipment(long detailID, int equipmentTypeID, String equipmentID, long orderID){
db.execSQL("INSERT OR REPLACE INTO " + TABLE_EQUIPMENT + " (" +
KEY_DETAIL_EQUIPMENT_ID + ", " + KEY_EQUIPMENT_CATEGORY + ", " + KEY_EQUIPMENT_ID + ",
" + KEY_ORDER_ID + ") VALUES (" + detailID + ", " + equipmentTypeID + ", '" + equipmentID + "', " +
orderID + ")");
}
Con la siguiente funcion cojeremos los datos de la tabla de pedidos para mostrarlos en la lista:
public Cursor getOrderListing(int orderType) {
String where;
if (orderType == ORDER_TYPE_OUTGOING)
where = "(" + KEY_ORDER_STATUS + " >= 0 AND " + KEY_ORDER_STATUS + " <= 3) OR (" +
KEY_ORDER_STATUS + " >= 18 AND " + KEY_ORDER_STATUS + " <= 23) OR (" + KEY_ORDER_STATUS
+ " >= 28 AND " + KEY_ORDER_STATUS + " <= 29)";
else
where = "(" + KEY_ORDER_STATUS + " >= 4 AND " + KEY_ORDER_STATUS + " <= 17) OR (" +
KEY_ORDER_STATUS + " >= 24 AND " + KEY_ORDER_STATUS + " <= 26) OR (" + KEY_ORDER_STATUS
+ " = 30)";
String sql = "SELECT * FROM " + TABLE_ORDER + " WHERE " + where;
return db.rawQuery(sql, new String[]{});
}
6.5 Codigo
Y el codigo completo seria el sguiente:
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DBAbaco {
private static final String TAG = "DBAbaco";
public static final String DATABASE_NAME = "AbacoUser";
public static final int DATABASE_VERSION = 36;
public static final String KEY_USER_NAME = "nombre_usuario";
public static final String KEY_USER_PASSWORD = "contraseña_usuario";
public static final String KEY_ORDER_ID = "id_pedido";
public static final String KEY_ORDER_STATUS = "estado";
public static final String KEY_ORDER_STATUS_WORD = "significado";
public static final String KEY_CLIENT_ID = "id_cliente";
public static final String KEY_DETAIL_EQUIPMENT_ID = "id_detalle";
26. public static final String KEY_EQUIPMENT_ID = "id_equipo";
public static final String KEY_EQUIPMENT_CATEGORY = "categoria_equipo";
public static final String KEY_EQUIPMENT_DESCRIPTION = "descripcion_equipo";
public static final String KEY_CLIENT_NAME = "nombre";
public static final String KEY_COMPONENT = "componente";
public static final String KEY_COMPONENT_SENT = "componente_enviado";
public static final String KEY_COMPONENT_RETURN = "componente_devuelto";
public static final String KEY_EQUIPMENT_GAMMA = "Gamma";
public static final String KEY_DETAIL_ORDER_ID = "id_detalle_pedido";
public static final String TABLE_USER = "Usuarios";
public static final String TABLE_ORDER_STATUS = "Estado ordenes";
public static final String TABLE_ORDER = "Pedidos";
public static final String TABLE_EQUIPMENT = "Equipos";
public static final String TABLE_COMPONENT = "Componentes";
public static final String TABLE_DETAIL_ORDER = "OrderDetail";
private static final String CREATE_TABLE_USER =
"CREATE TABLE IF NOT EXISTS " + TABLE_USER
+ " (" + KEY_USER_NAME + " text not null, "
+ KEY_USER_PASSWORD + " int(4) not null "
+ ");";
private static final String CREATE_TABLE_ORDER_STATUS =
"CREATE TABLE IF NOT EXISTS " + TABLE_ORDER_STATUS
+ " (" + KEY_ORDER_STATUS + " int PRIMARY KEY, "
+ KEY_ORDER_STATUS_WORD + " text not null "
+ ");";
private static final String CREATE_TABLE_ORDER =
"CREATE TABLE IF NOT EXISTS " + TABLE_ORDER
+ " (" + KEY_ORDER_ID + " REAL PRIMARY KEY, "
+ KEY_ORDER_STATUS + " int not null, "
+ KEY_CLIENT_ID + " REAL not null, "
+ KEY_CLIENT_NAME + " NVARCHAR(100) not null "
+ "FOREIGN KEY(" + KEY_ORDER_STATUS + ") REFERENCES " +
TABLE_ORDER_STATUS + "(" + KEY_ORDER_STATUS
+ "));";
private static final String CREATE_TABLE_EQUIPMENT =
"CREATE TABLE IF NOT EXISTS " + TABLE_EQUIPMENT
+ " (" + KEY_DETAIL_EQUIPMENT_ID + " REAL not null, "
+ KEY_EQUIPMENT_CATEGORY + " text not null, "
+ KEY_EQUIPMENT_ID + " INT not null, "
+ KEY_ORDER_ID + " REAL not null, "
+ "FOREIGN KEY(" + KEY_ORDER_ID + ") REFERENCES " + TABLE_ORDER
+ "(" + KEY_ORDER_ID
+ "));";
private static final String CREATE_TABLE_COMPONENT =
"CREATE TABLE IF NOT EXISTS " + TABLE_COMPONENT
+ " (" + KEY_DETAIL_EQUIPMENT_ID + " text not null, "
+ KEY_COMPONENT + " text not null, "
+ KEY_COMPONENT_SENT + " text not null, "
+ KEY_COMPONENT_RETURN + " text not null, "
+ "FOREIGN KEY(" + KEY_DETAIL_EQUIPMENT_ID + ") REFERENCES " +
TABLE_EQUIPMENT + "(" + KEY_DETAIL_EQUIPMENT_ID
+ "));";
private static final String CREATE_TABLE_ORDER_DETAIL =
"CREATE TABLE IF NOT EXISTS " + TABLE_DETAIL_ORDER
+ " (" + KEY_ORDER_ID + " int not null, "
+ KEY_DETAIL_EQUIPMENT_ID + " text not null, "
+ "FOREIGN KEY(" + KEY_ORDER_ID + ") REFERENCES " + TABLE_ORDER
+ "(" + KEY_ORDER_ID + "), "
+ "FOREIGN KEY(" + KEY_DETAIL_EQUIPMENT_ID + ") REFERENCES " +
TABLE_EQUIPMENT + "(" + KEY_DETAIL_EQUIPMENT_ID
+ "));";
public static final int COL_USER = 0;
public static final int COL_ORDER_ID = 0;
27. public static final int COL_EQUIPMENT_DETAIL_ID = 0;
public static final int COL_EQUIPMENT_CATEGORY = 1;
public static final int COL_EQUIPMENT_ID = 2;
public static final int COL_EQUIPMENT_ORDER_ID = 3;
public static final int COL_ORDER_DETAIL_ID = 0;
public static final int COL_ORDER_DETAIL_EQUIPMENT_ID = 1;
public static int ORDER_TYPE_OUTGOING = 1;
public static int ORDER_TYPE_INCOMING = 2;
public final Context context;
private DatabaseHelper myDBHelper;
protected SQLiteDatabase db;
public DBAbaco(Context ctx) {
this.context = ctx;
myDBHelper = new DatabaseHelper(context);
}
public DBAbaco open() {
db = myDBHelper.getWritableDatabase();
return this;
}
public void close() {
myDBHelper.close();
}
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase _db) {
_db.execSQL(CREATE_TABLE_USER);
_db.execSQL(CREATE_TABLE_ORDER_STATUS);
_db.execSQL(CREATE_TABLE_ORDER);
_db.execSQL(CREATE_TABLE_EQUIPMENT);
_db.execSQL(CREATE_TABLE_COMPONENT);
_db.execSQL(CREATE_TABLE_ORDER_DETAIL);
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_USER + " (" + KEY_USER_NAME
+ ", " + KEY_USER_PASSWORD + ") VALUES ('GORKA', 1234)");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_USER + " (" + KEY_USER_NAME
+ ", " + KEY_USER_PASSWORD + ") VALUES ('IRATXE', 1234)");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_USER + " (" + KEY_USER_NAME
+ ", " + KEY_USER_PASSWORD + ") VALUES ('INMA', 1234)");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_USER + " (" + KEY_USER_NAME
+ ", " + KEY_USER_PASSWORD + ") VALUES ('RAUL', 1234)");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (0, 'Presupuesto')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (2, 'Confirmado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (3, 'Pagado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (4, 'Enviado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (6, 'Devuelto')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (7, 'Recoger')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (8, 'Fianza devuelta')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (9, 'Comprobado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (10, 'Envio solicitado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (11, 'Devolucion solicitada')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
28. KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (12, 'Recogido en local')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (14, 'Presupuesto')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (15, 'Confirmado local')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (16, 'Cancelado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (17, 'Devuelto local')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (18, 'Uso en local')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (20, 'Email enviado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (21, 'Preparado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (22, 'Cancelado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (23, 'Contrato aceptado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (24, 'Contrato desmarcado')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (25, 'Fianza NO devuelta')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (26, 'Devuelto, falta material')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (27, 'Envio fallido')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (28, 'Continua en otra
reserva')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (29, 'Ampliacion reserva')");
_db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER_STATUS + " (" +
KEY_ORDER_STATUS + ", " + KEY_ORDER_STATUS_WORD + ") VALUES (30, 'Solicitados comentarios')");
}
@Override
public void onUpgrade(SQLiteDatabase _db, int oldVersion, int newVersion) {
_db.execSQL("DROP TABLE IF EXISTS " + TABLE_USER);
_db.execSQL("DROP TABLE IF EXISTS " + TABLE_ORDER);
_db.execSQL("DROP TABLE IF EXISTS " + TABLE_EQUIPMENT);
_db.execSQL("DROP TABLE IF EXISTS " + TABLE_COMPONENT);
_db.execSQL("DROP TABLE IF EXISTS " + TABLE_DETAIL_ORDER);
onCreate(_db);
}
}
public void dropTables(){
db.execSQL("DROP TABLE IF EXISTS " + TABLE_ORDER);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_EQUIPMENT);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_COMPONENT);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_DETAIL_ORDER);
}
public void createTables(){
db.execSQL(CREATE_TABLE_ORDER);
db.execSQL(CREATE_TABLE_EQUIPMENT);
db.execSQL(CREATE_TABLE_COMPONENT);
db.execSQL(CREATE_TABLE_ORDER_DETAIL);
}
public Cursor getUserListing() {
String sql = "SELECT * FROM " + TABLE_USER;
return db.rawQuery(sql, new String[]{});
}
public void insertOrder(long orderID, int status,long clientID, String clientName){
db.execSQL("INSERT OR REPLACE INTO " + TABLE_ORDER + " (" + KEY_ORDER_ID + ", " +
29. KEY_ORDER_STATUS + ", " + KEY_CLIENT_ID + ", " + KEY_CLIENT_NAME + ") VALUES (" + orderID +
", " + status +", " + clientID + ", '" + clientName + "')");
}
public void insertEquipment(long detailID, int equipmentTypeID, String equipmentID, long orderID){
db.execSQL("INSERT OR REPLACE INTO " + TABLE_EQUIPMENT + " (" +
KEY_DETAIL_EQUIPMENT_ID + ", " + KEY_EQUIPMENT_CATEGORY + ", " + KEY_EQUIPMENT_ID + ",
" + KEY_ORDER_ID + ") VALUES (" + detailID + ", " + equipmentTypeID + ", '" + equipmentID + "', " +
orderID + ")");
}
public Cursor getOrderListing(int orderType) {
String where;
if (orderType == ORDER_TYPE_OUTGOING)
where = "(" + KEY_ORDER_STATUS + " >= 0 AND " + KEY_ORDER_STATUS + " <= 3) OR
(" + KEY_ORDER_STATUS + " >= 18 AND " + KEY_ORDER_STATUS + " <= 23) OR (" +
KEY_ORDER_STATUS + " >= 28 AND " + KEY_ORDER_STATUS + " <= 29)";
else
where = "(" + KEY_ORDER_STATUS + " >= 4 AND " + KEY_ORDER_STATUS + " <= 17) OR
(" + KEY_ORDER_STATUS + " >= 24 AND " + KEY_ORDER_STATUS + " <= 26) OR (" +
KEY_ORDER_STATUS + " = 30)";
String sql = "SELECT * FROM " + TABLE_ORDER + " WHERE " + where;
return db.rawQuery(sql, new String[]{});
}
}