今日已更新 84 条资讯 | 累计 37635 条内容
关于我们

标签:#Java

找到 1193 篇相关文章

AI 资讯

Compressing an image to exactly 50KB in the browser, with no server

Indian government exam portals have a rule that has quietly shaped a lot of my code: your photo must be under 50KB . Not "small". Not "optimised". Under 50KB, or the upload is rejected. Every free tool I found for this wanted me to upload the photo to a server, wait in a queue, and create an account. For a file I just wanted to shrink. So I wrote it myself, in the browser. This post is about the actual technique — hitting an exact byte target with canvas — and, honestly, about where my implementation still falls short. The naive version, and why it fails The obvious approach: canvas . toBlob ( blob => download ( blob ), ' image/jpeg ' , 0.7 ); Pick a quality, hope for the best. The problem is that JPEG quality has no predictable relationship to output size. Quality 0.7 on a flat, low-detail portrait might land at 18KB. The same 0.7 on a noisy, high-detail photo lands at 210KB. You cannot compute the quality you need — the encoder decides, and it depends entirely on image content. So you can't calculate it. You have to search for it. Binary search on quality toBlob is cheap enough to call repeatedly, and quality is monotonic — higher quality never produces a smaller file. That's exactly the setup binary search wants. function encode ( canvas , quality ) { return new Promise ( resolve => canvas . toBlob ( resolve , ' image/jpeg ' , quality ) ); } async function compressToTarget ( canvas , targetBytes ) { let lo = 0.05 , hi = 0.95 , best = null ; for ( let i = 0 ; i < 8 ; i ++ ) { const mid = ( lo + hi ) / 2 ; const blob = await encode ( canvas , mid ); if ( blob . size <= targetBytes ) { best = blob ; // fits — remember it, try for better quality lo = mid ; } else { hi = mid ; // too big — back off } } return best ; } Eight iterations over the range 0.05–0.95 narrows quality to about ±0.002, far finer than anyone can see. Each iteration is one encode; on a typical phone photo the whole loop runs in well under a second. Two details that matter more than they look: Keep

2026-07-29 原文 →
AI 资讯

Handling Asynchronous Webhook Notifications & Callbacks in Joget via BeanShell

Handling Asynchronous Webhook Notifications & Callbacks in Joget via BeanShell When integrating Joget DX with external platforms—such as payment gateways, SMS providers, or ERP systems—requests are often processed asynchronously. The external system accepts a request immediately and dispatches an HTTP POST webhook callback to Joget minutes or hours later when processing completes. Receiving webhook callbacks inside BeanShell API endpoints requires two key tasks: Safe Variable Type Coercion: Handling parameter arrays ( String[] ) versus single strings ( String ) safely without throwing ClassCastException . FormDataDao Persistence: Saving or updating the notification payload inside a Joget form database table using FormDataDao . In this guide, we'll write a defensive Java/BeanShell script that receives asynchronous webhook callbacks and logs them cleanly into Joget. Architecture Overview Webhook Endpoint: An external system hits your Joget API endpoint with callback parameters (e.g. process_id , status , response_payload , recipient ). Type Extraction: A safe helper function handles parameter type variations (whether passed via URL query params or JSON request bodies). FormDataDao Save: Instead of executing raw JDBC queries, the script uses FormDataDao to persist a FormRowSet directly into Joget's form storage engine. The BeanShell Script Place this code inside your API Builder BeanShell script or custom REST endpoint: import org.joget.apps.app.service.AppUtil ; import org.joget.apps.form.dao.FormDataDao ; import org.joget.apps.form.model.FormRow ; import org.joget.apps.form.model.FormRowSet ; import org.joget.commons.util.LogUtil ; import java.util.UUID ; // 1. Safe Type Extraction Helper public String safeExtract ( Object param ) { if ( param == null ) return "" ; try { if ( param instanceof String []) { String [] arr = ( String []) param ; return arr . length > 0 ? arr [ 0 ] : "" ; } if ( param instanceof String ) { return ( String ) param ; } } catch ( Throwable t

2026-07-29 原文 →
AI 资讯

Generating Multilingual HTML Reports with Attachment Download Links in Joget

Generating Multilingual HTML Reports with Attachment Download Links in Joget Creating customized executive report summaries in Joget DX often requires more than simple database lists. Real-world business reports frequently need to join multiple tables, translate status labels based on the user's active locale ( #platform.currentLocale# ), and generate secure file download links for form attachments. In this guide, we'll build a Java/BeanShell script that queries main records and history logs, resolves internationalization ( i18n ) message keys dynamically, and generates interactive HTML reports embedded with secure attachment links. Key Components Dynamic i18n Translation: Uses AppUtil.processHashVariable("#i18n.key#", null, null, null) to convert database status codes into localized text matching the user's language setting. File Attachment Links: Formats secure file download URLs ( /jw/web/client/app/{appId}/{version}/form/download/{tableName}/{recordId}/{fileName} ) so users can open uploaded documents directly from the report summary. Multi-Table SQL Join: Merges main request details, audit transaction history, and custom review tables into a clean HTML document layout. The BeanShell Script Place this code inside a BeanShell Form Bounding Box or an HTML Report Generator tool step: import java.sql.Connection ; import java.sql.PreparedStatement ; import java.sql.ResultSet ; import java.net.URLEncoder ; import javax.sql.DataSource ; import org.joget.apps.app.service.AppUtil ; import org.joget.apps.app.model.AppDefinition ; import org.joget.commons.util.LogUtil ; // Helper: Resolve i18n hash variables dynamically public String getLocalizedText ( String messageKey ) { if ( messageKey == null || messageKey . isEmpty ()) return "" ; String hashVariable = "#i18n." + messageKey + "#" ; return AppUtil . processHashVariable ( hashVariable , null , null , null ); } String recordId = "#requestParam.id#" ; if ( recordId == null || recordId . trim (). isEmpty ()) { return "<di

2026-07-29 原文 →
AI 资讯

How to Update Joget App Environment Variables Programmatically in BeanShell

How to Update Joget App Environment Variables Programmatically in BeanShell In Joget DX, App Environment Variables are commonly used to store global configuration values—such as API endpoints, tax rates, batch counter sequences, or feature flags. While administrators can update these variables manually through Joget App Center, enterprise workflows often need to update environment variables programmatically (for example, incrementing a daily batch sequence counter or updating an OAuth access token). In this guide, we'll write a short BeanShell script using Joget's EnvironmentVariableDao to fetch and update App Environment Variables dynamically. How It Works Obtain App Context: AppUtil.getCurrentAppDefinition() retrieves the active application definition. Access the DAO Bean: AppUtil.getApplicationContext().getBean("environmentVariableDao") retrieves Joget's internal DAO for environment variables. Load & Update: environmentVariableDao.loadById(envVarId, appDef) retrieves the target variable instance. Modifying .setValue() and executing environmentVariableDao.update(envVar) persists the updated value immediately. The Code Place this BeanShell snippet inside a BeanShell Tool workflow step or a Form Post-Processing Tool : import org.joget.apps.app.dao.EnvironmentVariableDao ; import org.joget.apps.app.model.AppDefinition ; import org.joget.apps.app.model.EnvironmentVariable ; import org.joget.apps.app.service.AppUtil ; import org.joget.commons.util.LogUtil ; public void updateAppEnvironmentVariable ( String variableId , String newValue ) { AppDefinition appDef = AppUtil . getCurrentAppDefinition (); if ( appDef != null ) { // Retrieve Joget's Environment Variable DAO bean EnvironmentVariableDao envDao = ( EnvironmentVariableDao ) AppUtil . getApplicationContext (). getBean ( "environmentVariableDao" ); // Load target environment variable by ID EnvironmentVariable envVar = envDao . loadById ( variableId , appDef ); if ( envVar != null ) { LogUtil . info ( "EnvVar Manager

2026-07-29 原文 →
AI 资讯

Custom Cell Renderers & Action Buttons in Joget Spreadsheet Elements

Custom Cell Renderers & Action Buttons in Joget Spreadsheet Elements The built-in Spreadsheet Element in Joget DX provides a spreadsheet-like interface for managing tabular records inside forms. However, standard spreadsheet columns only support basic text or dropdown inputs out of the box. If you want to add row-level action buttons (like a Delete Row button) or turn plain cell text into an interactive Modal Popup Link , you can supply custom Handsontable renderer functions directly inside your Spreadsheet column properties. In this guide, we'll look at two practical examples: adding a custom row-deletion button and rendering interactive drill-down links. Example 1: Adding a Custom Delete Row Button In your Joget Spreadsheet element, open column properties for an action column and configure the custom renderer function below: {{ renderer : function ( instance , td , row , col , prop , value , cellProperties ) { // Render custom HTML button inside the cell td . innerHTML = " <button type='button' class='btn-delete-row'>Delete</button> " ; td . style . textAlign = " center " ; // Attach click handler to remove the target row from the Handsontable instance const btn = td . querySelector ( " .btn-delete-row " ); btn . onclick = function ( e ) { e . preventDefault (); e . stopPropagation (); // Get underlying Handsontable instance from the form field const hotInstance = FormUtil . getField ( " your_spreadsheet_field_id " ). data ( " hot " ); if ( hotInstance ) { hotInstance . alter ( " remove_row " , row ); } }; } }} Key Highlights: instance.alter("remove_row", row) removes the target row directly from the underlying data model. e.stopPropagation() prevents Handsontable from entering cell-edit mode when the button is clicked. Example 2: Interactive Drill-Down Popup Links To display a clickable link in a grid cell that opens a detailed record inside a Joget modal dialog (popup iframe), use this cell renderer: {{ renderer : function ( instance , td , row , col , prop , va

2026-07-29 原文 →
AI 资讯

The Hidden Cost of a Log Line : Sync/Async Flush and everything in Between

log.info("user logged in") looks free. It isn't. Behind that one line is a chain of decisions — buffer or not, flush or not, block or drop, same thread or another — and each one trades latency , throughput , and durability against the others. This post walks the whole chain, from the method call down to the bytes hitting the disk platter. If you've ever wondered why your p99 latency has a mysterious spike, why logs vanish after a crash, or what "async logging" actually buys you, this is for you. First, the map: facade vs. implementation Java logging is a two-layer cake, and mixing up the layers is the #1 source of confusion. The facade is the API your code calls. The implementation is what actually writes the bytes. your code │ log.info(...) ▼ ┌───────────────────────────────┐ │ Facade: SLF4J (or Log4j2 API)│ ← the interface you compile against └──────────────┬────────────────┘ │ bound at runtime ┌───────────┼────────────┬──────────────┐ ▼ ▼ ▼ ▼ Logback Log4j2 Core java.util.logging ... (the engine that buffers, formats, and flushes) SLF4J — the de-facto standard facade. Your app should log against this. Logback — the reference SLF4J implementation. Solid, widely deployed. Log4j2 — the performance-focused implementation, famous for its lock-free async loggers. java.util.logging (JUL) — built into the JDK, rarely chosen on purpose. Why the split? So you can swap engines without touching a single log. call. Everything interesting in this post — the buffering, the flushing, the async magic — happens in the implementation layer. The anatomy of a single log call Before we talk flushing, let's see what one log.info(...) actually does. There are five stages: 1. Level check → is INFO enabled for this logger? (cheap, often the fastest bail-out) 2. Build LogEvent → capture message, timestamp, thread, MDC context, maybe a stack trace 3. Filter → run any configured filters 4. Layout / encode → turn the event into bytes ("2026-07-28 12:00:01 INFO ...") 5. Append → write those by

2026-07-29 原文 →
开发者

Top 5 Node.js ORMs Every Developer Should Know in 2026

Working with databases is a big part of backend development, and choosing the right ORM can save you hours of work. Here are five of the most popular Node.js ORMs, along with their strengths and weaknesses, to help you pick the right one for your next project. 1. Prisma A modern, type-safe ORM built for TypeScript with an excellent developer experience. Pros • Great TypeScript support • Easy migrations • Excellent DX • Large community Cons • Less flexible for advanced SQL • Requires client generation Drizzle ORM A lightweight, SQL-first ORM focused on performance and simplicity. Pros • Very fast • Full TypeScript support • SQL-first approach • Lightweight Cons • Smaller ecosystem • Better if you know SQL 3. TypeORM A mature ORM with broad database support, widely used in enterprise and legacy projects. Pros • Rich feature set • Supports many databases • Strong relationship support Cons • More complex API • Slower development than newer ORMs 4. MikroORM A powerful TypeScript ORM designed for large and complex applications. Pros • Excellent relationship handling • High flexibility • Strong TypeScript integration Cons • Steeper learning curve • Smaller community 5. Sequelize One of the oldest and most established ORMs in the Node.js ecosystem. Pros • Battle-tested • Supports many databases • Large legacy adoption Cons • TypeScript support is weaker • Feels outdated compared to modern ORMs Which ORM do you use the most? 👇

2026-07-29 原文 →
AI 资讯

Building Local AI Agents in Java with Tools4AI and Ollama: An Insurance Claims Use Case

Tools4AI is a 100% Java agentic AI framework that turns any annotated Java method into an AI-callable action. Ollama runs open models like Llama 3.1 and Phi-4 locally and exposes an OpenAI-compatible API. Point Tools4AI at http://localhost:11434/v1 and you get a fully offline, on-premise AI agent — no data ever leaves your network. In this tutorial we build an insurance claims triage agent that reads a claimant's free-text incident report, routes it to the right business action, extracts structured data, gates high-value payouts behind a human approval, and records a compliance audit trail. Who is this for? Java developers, solution architects, and engineering leaders in regulated industries (insurance, banking, healthcare) who want agentic AI without sending sensitive data to a third-party API . Table of Contents Why local AI agents matter for insurance Insurance runs on personally identifiable information (PII) : names, addresses, policy numbers, medical details, vehicle data, and loss descriptions. Sending that data to a hosted LLM API creates regulatory, contractual, and reputational risk. At the same time, claims teams are drowning in unstructured text — First Notice of Loss (FNOL) reports, adjuster notes, emails, and call transcripts. A local AI agent solves both problems at once: Data never leaves your premises. The model runs on your own hardware via Ollama. Deterministic business logic stays in Java. The LLM decides what to do; your audited, tested Java code decides how . Human-in-the-loop and audit trails are first-class, so you can satisfy compliance reviewers. That combination — private inference plus governed execution — is exactly what Tools4AI + Ollama gives you. What is Tools4AI? Tools4AI ( io.github.vishalmysore:tools4ai on Maven Central) is a lightweight, pure-Java agentic AI framework and ADK. Its core idea is simple and powerful: Annotate a Java class with @Agent and its methods with @Action . Tools4AI scans the classpath, and at runtime it maps

2026-07-29 原文 →
AI 资讯

Remix 3 Beta Preview Ditches React for a Web-Standards Full-Stack Framework

Remix 3 is a full-stack web framework that moves away from React, focusing on web platform primitives. It integrates routes, request handlers, and UI components into a single structure, utilizing a forked Preact for the frontend. Unlike previous versions, it emphasizes server ownership of the request lifecycle. Migration from Remix 2 is not straightforward, as it requires changes to existing apps. By Daniel Curtis

2026-07-28 原文 →
AI 资讯

React Performance Optimization Techniques That Actually Work

Performance optimization in React is often surrounded by myths. Developers routinely wrap every single component in React.memo , wrap every function in useCallback , and wonder why their application is still sluggish or memory-heavy. Premature optimization can actually degrade app performance and clutter your codebase. To build fast React applications, you need techniques that address actual bottlenecks: unnecessary re-renders, unoptimized state placement, oversized bundles, and main-thread blocking. Here are five practical React performance optimization techniques that deliver measurable results in production. 1. Push State Down (Fix Rerender Cascades) Before reaching for useMemo or React.memo , evaluate your state placement . When state lives too high up in the component tree, every state update forces the entire sub-tree to re-render. ❌ The Anti-Pattern: State at the Root // Changing `color` forces <HeavyChartComponent/> and <ComplexTable/> to re-render! export default function App () { const [ color , setColor ] = useState ( ' #6366f1 ' ); return ( < div > < input type = "color" value = { color } onChange = { ( e ) => setColor ( e . target . value ) } /> < p style = { { color } } > Sample Text </ p > < HeavyChartComponent /> < ComplexTable /> </ div > ); } ✅ The Fix: Component Isolation Move the isolated state and its control into its own dedicated child component: Javascript function ColorPicker () { const [ color , setColor ] = useState ( ' #6366f1 ' ); return ( < div > < input type = "color" value = { color } onChange = { ( e ) => setColor ( e . target . value ) } /> < p style = { { color } } > Sample Text </ p > </ div > ); } export default function App () { return ( < div > < ColorPicker /> { /* These components are no longer impacted by color state changes */ } < HeavyChartComponent /> < ComplexTable /> </ div > ); } 2. Pass Components as Children (Component Composition) Sometimes state must remain in a parent component, but you don't want child components

2026-07-28 原文 →
AI 资讯

Solon Cloud: The Distributed Toolkit That Doesn't Lock You In

When I first looked at Solon Cloud, I expected another opinionated microservice framework—the kind that tells you exactly which registry, which config center, and which message queue to use. What I found instead was a different philosophy: a set of interface standards with swappable plugin implementations . You write your code against the interfaces, and switching from local development to production Cloud is a YAML change, not a code rewrite. Let me walk through how it works. The Core Idea: An Anti-Corruption Layer Solon Cloud isn't a single product. It's a collection of 13 service interfaces backed by a plugin ecosystem. The official docs call it a "通用防腐层" (general anti-corruption layer), and the name fits. Here's the architecture: Your Business Code ↓ (uses CloudClient or annotations) ┌─────────────────────────────────────┐ │ Solon Cloud Interfaces │ │ (CloudConfigService, CloudEvent, │ │ CloudDiscoveryService, ...) │ ├─────────────────────────────────────┤ │ Plugin: local │ Plugin: water │ │ Plugin: nacos │ Plugin: consul │ │ Plugin: ... │ │ └─────────────────────────────────────┘ Your code depends on the interfaces. The plugins implement them. You swap the dependency and the YAML config—the code stays untouched. The 13 Service Interfaces From the official family page, Solon Cloud defines these capability interfaces: Interface Purpose CloudConfigService Distributed configuration CloudDiscoveryService Service registration & discovery CloudEventService Distributed event bus CloudFileService Distributed file storage CloudI18nService Distributed i18n CloudIdService Distributed ID generation CloudJobService Distributed scheduled jobs CloudListService Distributed whitelist/blacklist CloudLockService Distributed locking CloudLogService Distributed logging CloudMetricService Distributed metrics CloudTraceService Distributed tracing CloudBreakerService Circuit breaker Each interface has a corresponding configuration namespace ( solon.cloud.@@.xxx ) and a set of plugin im

2026-07-28 原文 →
AI 资讯

Building a Modern CRM Dashboard with React, Tailwind CSS, and Recharts

Building a modern Customer Relationship Management (CRM) platform requires more than just displaying raw database records. Users expect interactive analytics, clear data visualization, responsive layouts, and lightning-fast UI updates . In this guide, we'll walk through architecting a sleek, responsive CRM analytics dashboard using React , Tailwind CSS , and Recharts . 1. Dashboard Architecture & Component Hierarchy To keep our CRM modular and easy to maintain, we break down the UI into specialized components: src/ ├── components/ │ ├── layout/ │ │ ├── Sidebar.jsx │ │ └── Header.jsx │ ├── dashboard/ │ │ ├── MetricCard.jsx │ │ ├── RevenueChart.jsx │ │ └── RecentDealsTable.jsx └── pages/ └── Dashboard.jsx 2. Key Performance Metric Cards KPI cards sit at the top of the dashboard to give team leaders instant insight into active pipeline value, customer acquisition, and conversion rates. Here is a clean, reusable MetricCard component built with Tailwind CSS: import React from ' react ' ; import { TrendingUp , TrendingDown } from ' lucide-react ' ; export const MetricCard = ({ title , value , change , isPositive , icon : Icon }) => { return ( < div className = "bg-white dark:bg-slate-900 p-6 rounded-2xl border border-slate-200 dark:border-slate-800 shadow-sm transition-all hover:shadow-md" > < div className = "flex items-center justify-between" > < span className = "text-sm font-medium text-slate-500 dark:text-slate-400" > { title } </ span > < div className = "p-2.5 rounded-xl bg-indigo-50 text-indigo-600 dark:bg-indigo-950/50 dark:text-indigo-400" > < Icon className = "w-5 h-5" /> </ div > </ div > < div className = "mt-4 flex items-baseline justify-between" > < h3 className = "text-2xl font-bold text-slate-900 dark:text-white" > { value } </ h3 > < span className = { `inline-flex items-center text-xs font-semibold px-2 py-0.5 rounded-full ${ isPositive ? ' bg-emerald-50 text-emerald-600 dark:bg-emerald-950/50 dark:text-emerald-400 ' : ' bg-rose-50 text-rose-600 dark:bg

2026-07-28 原文 →
AI 资讯

SOLID Principles Cheat Sheet

Writing software that scales from a small monolith into a multi-team distributed system requires strict architectural discipline. The SOLID principles —coined by Robert C. Martin ("Uncle Bob")—serve as fundamental guidelines for object-oriented design and system architecture. When improperly understood, developers often fall into two extreme traps: creating monolithic "God objects" that break with every change, or over-engineering systems into hyper-fragmented, unmaintainable micro-services. In this deep-dive guide, we will break down each of the 5 SOLID principles from low-level class design up to high-level distributed systems design, complete with bad vs. refactored Java examples, system architecture diagrams, trade-off analyses, and a comprehensive cheat sheet. SOLID Principles Cheat Sheet Principle Core Concept Anti-Pattern / Code Smell Refactoring Solution Single Responsibility (SRP) A class or module should have one, and only one, reason to change (serving one business actor/domain). God Class / Micro-Fragmentation: Classes handling payment, DB, and notifications, OR over-fragmented single-function classes. Split by domain responsibility. Use orchestrator/coordinator components for workflows. Open/Closed (OCP) Software entities should be open for extension, but closed for modification . Conditional Bloat: Cascading if-else or switch statements checking object types or channels. Strategy Pattern, Dependency Injection, and Event-Driven Pub/Sub messaging (e.g., Kafka). Liskov Substitution (LSP) Subtypes must be completely substitutable for their base types without breaking client behavior. Runtime Exceptions: Subclasses throwing UnsupportedOperationException or silently breaking logic. Split fat inheritance hierarchies into granular, capability-specific interfaces. Interface Segregation (ISP) No client should be forced to depend on methods it does not use. Fat Interfaces: Monolithic interfaces forcing callers to mock or implement irrelevant methods. Role-focused

2026-07-28 原文 →