AI 资讯
Rest Template - API for developers- Spring Boot
RestTemplate is a synchronous Spring Framework client used to consume RESTful web services by simplifying HTTP communication. Synchronous Communication: It blocks the execution thread until a response is received.HTTP Methods: It provides built-in methods for standard operations like GET, POST, PUT, and DELETE.Automatic Mapping: It can automatically convert JSON or XML responses into Java domain objects using message converters.Status: While widely used, it is in maintenance mode. For new projects, Spring recommends using the modern RestClient or the reactive. Its an automate work. getForObject() Performs a GET request and returns the response body directly as an object. getForEntity() Performs a GET request and returns a ResponseEntity (includes status and headers). postForObject() Sends data via POST and returns the mapped response body. exchange() A general-purpose method for all HTTP verbs, offering full control over headers and request entities. getForObject- Controller Snippet Response is received in Object format. @RestController @RequestMapping("/api") public class ApiController { @Autowired private ApiService apiService; @GetMapping("/getUsers") public String users() { return apiService.getUsers(); } Service snippet: @Service public class ApiService { @Autowired private RestTemplate restTemplate; @Autowired UserApiRepo userApiRepo; public String getUsers() { String url = "https://jsonplaceholder.typicode.com/users"; String response = restTemplate.getForObject(url, String.class); return response; } Response: "id": 1, "name": "Leanne Graham", "username": "Bret", "email": "Sincere@april.biz", "address": { "street": "Kulas Light", "suite": "Apt. 556", "city": "Gwenborough", "zipcode": "92998-3874", "geo": { "lat": "-37.3159", "lng": "81.1496" } }, "phone": "1-770-736-8031 x56442", "website": "hildegard.org", "company": { "name": "Romaguera-Crona", "catchPhrase": "Multi-layered client-server neural-net", "bs": "harness real-time e-markets" } getForEntity() Respo
AI 资讯
How to Route Real-Time Gold and Silver Prices from a Unified WebSocket Stream
When I first connected to a precious metals WebSocket API, I expected to get a clean stream of prices. What I actually got was a firehose of mixed ticks—gold, silver, platinum—all arriving through the same callback. If you’ve ever tried to build a trading bot or a custom chart, you know this is a recipe for disaster. In this post, I’ll share how I solved the problem with a few lines of Python and a clear mapping strategy. The scenario: You have one WebSocket URL that pushes quotes for multiple metals. You need to separate them so you can update different UI components, run independent strategies, or store them in distinct database tables. The data pain point: every message uses the same JSON structure, and the only differentiator is a field like symbol . If you don’t act on it immediately, everything gets mixed up. Identify Assets via the Symbol Field Start by checking the API docs for the field that carries the instrument code. Usually it’s symbol , but instrumentId or type are also used. Here’s a typical reference table: Field Description Example symbol Asset code XAUUSD, XAGUSD instrumentId Internal platform ID 1001, 1002 type Asset class gold, silver I turn this into a dictionary mapping each symbol to a human-readable category: asset_map = { " XAUUSD " : " gold " , " XAGUSD " : " silver " , " XPTUSD " : " platinum " } Buffer Messages by Type Because these streams are high-frequency, I avoid processing every tick individually. Instead, the WebSocket callback just updates an in-memory store that is already grouped by asset type: # Keep the hot path extremely light def on_message ( msg ): symbol = msg [ ' symbol ' ] price = msg [ ' price ' ] asset_type = asset_map . get ( symbol , " unknown " ) cache [ asset_type ][ symbol ] = price Then, a background timer fetches the latest prices from cache["gold"] and cache["silver"] separately and does the actual work—like computing indicators or rendering charts. The key benefit is complete isolation: your gold logic never t
AI 资讯
Building a Custom API Using PL/SQL with ORDS
In modern application development, exposing database logic as REST APIs is a powerful way to integrate systems. Oracle REST Data Services (ORDS) makes it easy to turn PL/SQL into RESTful APIs without needing a separate backend service. In this blog, we’ll walk through how to create a simple POST API using ORDS and PL/SQL to insert data into a table. Pre-requisites A cloud-based ATP wallet (I prefer) Let's start how we create the APIs on the top of any custom table which relies on databases Create a table in the oracle SQL Developer and followed by create an ORDS Module 1.Create an ORDS Module A module is a logical container for related REST endpoints. What this Module does ?? Creates a module named nj_api Defines base URL: http://server_name/ords/table_Schema/nj_api/ 2: Define a Template (Endpoint Path) A template represents the API endpoint path. It defines how Endpoint URL:/ords/table_schema/nj_api/insert_data 3: Define the Handler (Business Logic) The handler contains the logic executed when the API is called. Key Concepts: p_method => 'POST': Defines HTTP method p_source_type => ORDS.source_type_plsql: Uses PL/SQL block Bind variables (:name, :num, etc.) map directly to JSON request body parameters 4: Testing the API Using Tools like Postman,cURL,ORDS REST Workshop I tested with Postman FYR Let's call same in Oracle VBCS in new blog. .. Try other methods like Delete, PATCH & GET
AI 资讯
Python Day Three – Lists, Indices, and Packing Your Virtual Backpack 🎒
Welcome back to Day 3, Python dynamic duo! 🚀 If you survived Day 2 , you now know how to create variables and throw strings, integers, floats, and booleans into their own little cardboard boxes. 📦 But what happens when you’re building a game and your character needs an inventory? Or you're making a shopping list app? Creating 50 different variables like item1, item2, item3 will make you want to throw your router out the window. 🪟💻 Today, we are leveling up our storage game. We are moving out of single cardboard boxes and packing a Virtual Backpack: Enter Lists! 🎒🎉 🎒 What is a List? In Python, a List is a data structure used to store a collection of items in one single variable. Think of it like a backpack where you can stuff multiple things inside, keep them in a specific order, and pull them out whenever you need them. Creating a list is simple. You use square brackets [] and separate your items with commas: # Packing our survival backpack 🗺️ backpack = [ " map " , " flashlight " , " water bottle " , " protein bar " ] print ( backpack ) # Prints: ['map', 'flashlight', 'water bottle', 'protein bar'] The coolest part? Python lists don’t care what you put inside. You can mix strings, integers, and booleans all in one single backpack (though usually, it makes the most sense to keep similar things together). 🤯 The First Rule of Coding Club: We Start Counting at Zero! Here is where programming turns your brain upside down. 🧠🙃 If I asked you what the first item in our backpack list is, you’d logically say "map". And you'd be right in human language. But in Python-speak, computer memory starts counting at 0. This is called Indexing. To pull a specific item out of your backpack, you write the name of the list followed by the item's position (index) inside square brackets: backpack = [ " map " , " flashlight " , " water bottle " , " protein bar " ] # Pulling out the items using their index 🔍 print ( backpack [ 0 ]) # Prints: map (The absolute first item!) print ( backpack [
AI 资讯
Gas Optimization Part 4: Solidity Tips for Cheaper Contracts
Every line of your smart contract costs something. Some lines cost more than others. In this part of our gas saving series, we’ll explore how to write smarter Solidity code that keeps your contract lean and efficient. Here are six simple and practical ways to reduce gas costs while writing Solidity smart contracts. 1. Use payable Only When Needed, But Know It Saves Gas In Solidity, a function marked payable can actually use slightly less gas than a non-payable one. Even if you're not sending ETH, the EVM skips some internal checks when the function is marked payable. See this example: function hello() external payable {} // 21,137 gas function hello2() external {} // 21,161 gas That tiny difference may not seem like much, but across thousands of calls, it adds up. Only use payable when your function is actually meant to accept ETH 2. Use unchecked for Safe Arithmetic When You’re Sure Since Solidity 0.8.0, all arithmetic operations automatically check for overflows and underflows. While this makes contracts safer, it also uses extra gas. When you're certain that overflow won't occur, you can use the unchecked keyword to skip these safety checks. uint256 public myNumber = 0; function increment() external { unchecked { myNumber++; } } Gas used: 24,347 (much cheaper than using safe math) Warning: Use unchecked carefully. Only when you're confident there's no risk of overflow. 3. Turn On the Solidity Optimizer The Solidity Optimizer is like a smart helper that cleans up and tightens your compiled bytecode. It does not change how your contract works, but it removes waste and makes it cheaper to run. If you’re using tools like Hardhat or Remix, always enable the Optimizer before deploying to mainnet. 4. Use uint256 Instead of Smaller Integers (Most of the Time) Smaller types like uint8 or uint16 might look more efficient, but they can cost more gas during execution. That’s because the EVM automatically converts them to uint256 behind the scenes. So, if you're not tightly p
AI 资讯
Building a Resume Download Gate: Email Collection, Signed Tokens, and an S3 Lesson
I wanted a soft gate on my resume download. Not a paywall. Just an email field — enough friction to filter bots, enough signal to know who's interested. What started as a straightforward feature turned into a three-part lesson: stateless token signing, S3 public access, and email delivery mechanics. Here's the full story. The Feature The flow I wanted: Visitor clicks "Download Resume" on the About page or Hero A modal asks for their email Backend validates the email (format + disposable domain check) A signed, time-limited link is emailed to them They click the link, the PDF opens No database tokens. No cron jobs. No permanent S3 URLs floating around. Part 1 — The Model and the Gate The Resume Model Resume follows the singleton pattern I already use for page headers — force pk=1 on every save, restrict add/delete in admin. One row, forever. class Resume ( models . Model ): pdf = models . FileField ( upload_to = " resume/ " , storage = private_resume_storage ) last_updated = models . DateField ( default = date . today ) def save ( self , * args , ** kwargs ): self . pk = 1 super (). save ( * args , ** kwargs ) ResumeDownloadRequest logs every email that requests a link — no tokens, no expiry columns, just a record of who asked and when. class ResumeDownloadRequest ( models . Model ): email = models . EmailField () created_at = models . DateTimeField ( auto_now_add = True ) unsubscribed = models . BooleanField ( default = False ) class Meta : ordering = [ " -created_at " ] The unsubscribed flag is there for a future newsletter broadcast — when a new blog post goes out, skip anyone who opted out. Blocking Disposable Emails Before signing anything, the email is checked against a frozenset of ~70 known throwaway domains: # core/validators.py DISPOSABLE_EMAIL_DOMAINS : frozenset [ str ] = frozenset ({ " mailinator.com " , " guerrillamail.com " , " yopmail.com " , " 10minutemail.com " , " trashmail.com " , # ... ~70 total }) def is_disposable_email ( email : str ) -> bool
AI 资讯
Git for GitHub: How to use simple Git commands to manage a GitHub repository
Recently, I was working on creating a website on a cloud-based IDE (CodeHS). One night, I was editing, and then when I was done, I simply turned off my monitor and disabled my mouse and keyboard. Then, the next day at school, I continued to work on the website, and made significant changes. When I got home, I made more significant changes, but then realized something very important. What I realized is that when I continued to work on the project at home, the cloud-based IDE hadn't refreshed to the new code, and overwrote the work I did at school when I saved my new work. So, what is the purpose of me telling you this? Is it to say that you should always close your code editor when you're done working, or some other trick to prevent this from happening? No, it definitely is not. After the initial panic, I realized that the cloud-based IDE had a history section, which has a detailed log of every change that happened to every file. I then looked back at my old copy, copied the changes, and put them back into my new code. Now, imagine you aren't using a cloud-based IDE, and your just editing a file on your computer, in an IDE, or simply your terminal. To clarify, Git is not cloud-based, it is local, (sitting on your computer), that connects to the cloud (GitHub). What happens when something breaks? For some environments, this could be catastrophic, and make you loose a lot of work. When you make an update to a file, the last state and all the states before it are gone. But, this isn't the only thing that can happen. When you use a version control system (VCS), like Git, you can always go back to your previous commits, (snapshots of your code). The work I almost lost wasn't very important; that work didn't effect anyone, except myself. Imagine what would happen if I was working on something more important, or even just working on something for a job. Before learning how to manage your project, it helps to understand what Git actually is. Git is overwhelmingly the most po
AI 资讯
First 90 days as a junior engineer on an AI-heavy team: what to learn first
You took the offer. The team uses Cursor or Copilot for almost every PR, runs an internal RAG bot over the docs, and at least one senior engineer is building agent workflows on the side. Your onboarding doc is half-written because the person who owned it left, and the codebase has roughly 40% more surface area than the org chart suggests, because LLMs have made it cheap to ship adapters, scripts, and one-off services nobody fully owns. This is the environment most junior engineers walk into in 2026. The traditional advice — read the codebase, ask questions, find a mentor — still applies, but it doesn't tell you what to prioritize when the senior engineers around you are visibly faster than you because they've internalized tools you've never touched. Below is a 90-day plan that assumes you have decent fundamentals (you can write a function, you understand HTTP, you've used git) but you're new to working in a codebase where AI is a first-class collaborator. Days 1-30: read more than you write, and read what the AI reads The biggest mistake juniors make in AI-heavy teams is opening Cursor on day three and trying to ship a feature. You will produce code that compiles, passes the obvious tests, and quietly violates three conventions nobody wrote down. Your PR will get approved by a tired senior because rejecting AI-generated junior code costs political capital. You will learn nothing. Instead, spend the first month doing three things in roughly equal proportion: 1. Read the codebase the way the AI reads it. Look at how the repo is structured for retrieval. Most AI-heavy teams have a CLAUDE.md , .cursorrules , AGENTS.md , or an internal RAG index. These files encode the conventions, the patterns the team wants reinforced, and — critically — the things the team has had to tell the AI not to do . Forbidden patterns are usually the result of an incident. Read them. Ask which incident produced each one. 2. Read closed PRs, not open ones. Open PRs are noisy. Closed PRs from th
AI 资讯
JSON Schema Validator Advanced Techniques for Power Users
Advanced JSON Schema Validator Techniques for Power Users Once you're comfortable with basic validation, these advanced techniques will help you handle complex validation scenarios and integrate validation deeply into your systems. 1. Conditional Validation with if/then/else The most powerful feature in modern JSON Schema is conditional validation. Use it to enforce different rules based on the data itself: { "type" : "object" , "properties" : { "type" : { "type" : "string" , "enum" : [ "individual" , "business" ] }, "taxId" : { "type" : "string" }, "businessName" : { "type" : "string" } }, "allOf" : [ { "if" : { "properties" : { "type" : { "const" : "business" } } }, "then" : { "required" : [ "taxId" , "businessName" ] }, "else" : { "properties" : { "taxId" : { "not" : {} }, "businessName" : { "not" : {} } } } } ] } This schema makes taxId and businessName required only when type is "business". For individual accounts, those fields must not be present. 2. Custom Error Messages with Error Message Extension Enhance validation with user-friendly error messages that guide users toward correct input: { "type" : "object" , "properties" : { "password" : { "type" : "string" , "minLength" : 8 , "pattern" : "^(?=.*[A-Z])(?=.*[0-9])" , "errorMessage" : { "minLength" : "Password must be at least 8 characters" , "pattern" : "Password must contain at least one uppercase letter and one number" } } } } While not part of the core JSON Schema spec, many validators (including AJV) support the errorMessage keyword for better user-facing error reporting. 3. Schema Composition with allOf, anyOf, and oneOf Combine multiple schemas to create sophisticated validation rules: { "allOf" : [ { "$ref" : "#/$defs/baseUser" }, { "$ref" : "#/$defs/withTimestamp" }, { "if" : { "properties" : { "role" : { "const" : "admin" } } }, "then" : { "$ref" : "#/$defs/adminPrivileges" } } ] } allOf: Data must match ALL sub-schemas (intersection) anyOf: Data must match AT LEAST ONE sub-schema (union) oneOf: Da
AI 资讯
Tipos de errores, Wrapping e Inspección en Go
Tabla de Contenidos Objetivo Restricciones de los Errores Basados en Texto Errores Personalizados en Go Conceptos Clave Implementar e Inspeccionar Errores Casos de Uso Comunes Para no morir en el intento y consejos que no pediste Conclusiones del Tema Objetivo Aprender a diseñar tipos de errores personalizados con metadatos de negocio en Go y a propagarlos correctamente a través del flujo de la aplicación sin perder su tipo ni su información de origen. Restricciones de los Errores Basados en Texto En programas sencillos, el uso de errors.New es perfecto. Sin embargo, en aplicaciones empresariales los errores necesitan transportar datos estructurados. Por ejemplo, si una validación de entrada falla, el frontend no solo quiere saber que "hubo un error", necesita saber qué campo exacto falló (ej. email ) y qué regla se violó (ej. formato inválido ). Si solo devolvemos una cadena de texto, la capa superior de nuestra aplicación tendría que parsear el texto del error con expresiones regulares para extraer los metadatos. Esto es extremadamente ineficiente, propenso a errores de formato y acopla la lógica interna a los mensajes de texto visibles al usuario. Tipos de Errores Comunes en Go Antes de analizar cómo propagar y envolver errores, es fundamental comprender los dos patrones principales que se utilizan en Go: Sentinel Errors : Son variables globales predefinidas que representan un estado de error estático y específico. Se definen a nivel de paquete y se comparan directamente por valor. Ejemplos estándar: io.EOF , sql.ErrNoRows . Creación: Generalmente declarados con errors.New (como var ErrNotFound = errors.New("not found") ). Custom Structs (Errores estructurados personalizados): Son estructuras que implementan la interfaz error y contienen campos adicionales para transportar metadatos dinámicos del fallo en tiempo de ejecución (como códigos de estado o parámetros de entrada). Creación: Un struct personalizado que implementa el método Error() (ej. type ValidationErr
AI 资讯
Understanding known_hosts and Host Key Verification: What It Protects Against and How TOFU Works
That "authenticity of host can't be established" message isn't just noise. Here's what's actually happening — and why blindly typing "yes" is a security mistake. Every developer has seen this: The authenticity of host 'example.com (203.0.113.1)' can't be established. ED25519 key fingerprint is SHA256:abc123xyz... Are you sure you want to continue connecting (yes/no/[fingerprint])? Almost everyone types yes without reading it. Then they move on. This message is SSH trying to protect you from one of the most dangerous attacks in network security: the man-in-the-middle attack. Understanding what's happening here — and what the ~/.ssh/known_hosts file actually does — will change how you think about every SSH connection you make. The Problem SSH Is Solving When you connect to ssh user@example.com , how do you know you're actually talking to example.com ? You can't rely on the IP address — IP addresses can be spoofed or rerouted. You can't rely on DNS — DNS can be poisoned. You can't rely on the network path — traffic can be intercepted at any point between you and the server. Without verification, an attacker positioned between you and the server could intercept the connection, pose as the server, decrypt everything you send, re-encrypt it, and forward it along. You'd type your password or authenticate with your key and never know the attacker saw every keystroke. This is a man-in-the-middle (MITM) attack . It's not theoretical. It happens on compromised networks, corporate proxies, malicious Wi-Fi hotspots, and misconfigured infrastructure. SSH's defense is host key verification . Every SSH server has a unique cryptographic identity — its host key. Before you exchange any sensitive data, the server proves it holds the private key corresponding to a public key you've previously verified. If the keys don't match, SSH warns you — loudly. What a Host Key Actually Is When OpenSSH is installed on a server, it automatically generates a set of host key pairs. These live in /etc
AI 资讯
v0 by Vercel Review: AI-Generated React Components That Actually Ship
I opened v0, typed "a settings page with profile editing, notification preferences, and a connected accounts section," and watched it generate a fully functional three-tab settings interface in under 40 seconds. The component used shadcn/ui primitives, Tailwind utility classes, and TypeScript types — the exact stack I would have chosen if I had written it from scratch. I copied the code, pasted it into my Next.js project, changed two import paths, and it rendered correctly on the first try. This is the v0 value proposition distilled: generate UI components that look like a senior frontend developer wrote them, then paste them into your real project without rewriting half the output. After generating 15 components across two weeks of real product work, I can confirm that v0 delivers on this promise more reliably than any general-purpose AI coding tool I have tested. But its scope is narrower than the marketing suggests, and understanding where v0 stops being useful is as important as knowing where it excels. The shadcn/ui Advantage v0 is built on top of shadcn/ui, and this is the single most important fact about how it works. shadcn/ui is not a component library in the traditional sense — it is a collection of copy-pasteable React components built on Radix UI primitives with Tailwind styling. When v0 generates a component, it uses these primitives directly, which means the output is consistent, accessible, and composable. The practical benefit is that v0-generated components integrate with your existing project without introducing a new design system. If you already use shadcn/ui — and a large and growing percentage of Next.js projects do — the generated components reuse your existing Button, Card, Dialog, and Input primitives. v0 just assumes you have them installed and generates code that expects them. If you do not have shadcn/ui in your project, v0 prompts you to run the initialization command before generating anything, which takes about 30 seconds. This archite
AI 资讯
GitHub Copilot Workspace Review: Task-Level AI Coding in the Browser
I tested GitHub Copilot Workspace on 12 real tasks across three repositories in May 2026 — a mix of bug fixes, feature additions, and documentation updates. My goal was to figure out whether the spec-first, browser-based workflow actually produces useful code, or whether it is a demo that falls apart when you ask it to do real work. The answer sits somewhere between impressive and frustrating, with the tool's success rate varying dramatically based on task size, repository maturity, and how well you write the initial specification. The Spec-First Workflow Forces Better Communication Copilot Workspace changes the AI coding interaction in one fundamental way that I have not seen elsewhere: you do not start with code, you start with a specification. When I opened Workspace on a Next.js project and typed "add rate limiting to the API routes using the existing rate-limit.ts utility," the system did not immediately generate code. It spent roughly 15 seconds reading my repository, then produced a three-step implementation plan: (1) import the rate-limit utility in each route, (2) wrap the route handler with the rate limiter, (3) add a test for the rate-limited behavior. I could approve the plan as-is, reject individual steps, or add revision notes before any code was written. On this particular task, the plan was correct and I approved it. Workspace then executed each step, modified five route files, and produced a draft pull request with a clear description and a summary of what changed. The entire process — from typing the specification to having a reviewable PR — took 4 minutes and 12 seconds. This planning phase is not window dressing. On a different task where I asked Workspace to "add WebSocket support to the chat feature," it read the repository and surfaced during planning that the project was deployed on Vercel's serverless functions, which do not support persistent WebSocket connections. It suggested using Vercel's Edge Functions with a third-party real-time serv
AI 资讯
Cursor IDE Review: What Makes It a Genuinely Different AI Code Editor
I switched my primary editor to Cursor in January of 2026 after spending three years on VS Code with GitHub Copilot. The reason was not the chatbot sidebar — every editor has one of those now — but the tab completion model that felt qualitatively different the first time I used it. After six months of daily use across TypeScript, Python, and Go projects, I have a clear picture of what Cursor actually changes about the coding experience and where the marketing outpaces the product. The Tab Completion Model Changed How I Write Code The first thing I noticed with Cursor was that I was pressing Tab instead of thinking about what to type next. That sounds minor, but after tracking my usage over a two-week comparison period, I found that Cursor's tab model correctly predicted my next edit 73 times out of 100 attempts in TypeScript files — measured by counting how often I accepted the ghost text suggestion versus how often I ignored it and typed manually. The mechanism behind this is Cursor's speculative continuation engine. It does not wait for you to stop typing before offering a suggestion. As you modify a function signature at the top of a file, the model silently recalculates the impact on every call site below. I tested this explicitly on a 340-line TypeScript service file where I renamed a parameter from userId to accountId . Before I could scroll to line 180 where the first call site appeared, Cursor had already ghost-written the updated argument. By the time I reached line 310, all six call sites had correct suggestions waiting. That multi-location awareness is what I have not seen any other editor replicate consistently. Not every language gets the same treatment. I ran the same completion acceptance test across three languages I work in regularly. TypeScript came in at the 73 percent acceptance rate I mentioned. Python was close behind at 68 percent. Go was noticeably worse at 51 percent, and the Go suggestions that I did accept frequently required minor correct
开发者
What the Heck is an API?
Table of Contents Intro The Restaurant The Menu Placing the Order The Plate Coming...