Posts Tagged ‘api’
[NDCOslo2024] Choosing The Best AWS Service For Your Website + API – Brandon Minnick
In the sprawling spectrum of cloud solutions, where a plethora of platforms perplex even the seasoned, Brandon Minnick, an AWS architect and mobile maestro, navigates the nebulous nebula of Amazon’s offerings. As a developer advocate with a penchant for demystifying deployment, Brandon dissects the dizzying array of AWS services—Lambda, Elastic Beanstalk, Lightsail, Amplify, S3—distilling their distinct domains to guide builders toward bespoke backends. His exploration, enriched with empirical evaluations, empowers enterprises to align ambition with architecture, balancing cost, celerity, and scalability.
Brandon begins with a confession: his own odyssey, as a mobile maestro thrust into AWS’s vast vault, was overwhelmed by options—acronyms and aliases abounding. His mission: map the maze, matching motives to mechanisms, ensuring websites and APIs ascend with alacrity.
Decoding the Domain: AWS’s Hosting Horizons
AWS’s arsenal is abundant: S3 stores static simplicities, buckets brimming with bits; Amplify augments apps, knitting frontends to functions. Brandon breaks down the basics: Elastic Beanstalk builds bridges, automating infrastructure; Lightsail lightens loads, offering preconfigured planes; Lambda launches lean, serverless scripts scaling seamlessly.
Each excels in its enclave: S3’s simplicity suits static sites, Amplify’s agility aids authenticated apps, Lambda’s litheness loves lightweight logic. Brandon’s benchmark: cost—S3’s cents versus Lambda’s low levies; speed—CloudFront’s celerity; scale—Fargate’s fluidity.
Cost and Celerity: Calculating the Calculus
Price predicates priority: S3’s storage starts at sub-dollar sums, Lambda’s invocations linger at $0.20 per million, Amplify’s adaptability aligns at $0.023 per GB. Brandon’s breakdown: static sites savor S3’s thrift, dynamic domains demand Amplify’s depth—authentication via Cognito, APIs via API Gateway.
Performance pulses: CloudFront’s CDN cuts latency to 300ms, Lambda’s cold starts cede to containers’ constancy. Brandon advises: weigh user whims—300ms matters for markets, less for leisurely loads.
Scalability and Simplicity: Structuring for Surge
Scalability shapes success: Lambda’s limitless leaps, Fargate’s fleet-footed fleets, Beanstalk’s balanced ballast. Brandon illustrates: API Gateway guards gates, throttling torrents; Amplify’s auto-scaling absolves administrative aches.
Simplicity seals the deal: Lightsail’s one-click launches lure lone developers; Amplify’s abstractions attract architects. Brandon’s beacon: start small—S3 for static, scale to Amplify for ambition.
Strategic Selection: Synthesizing Solutions
Brandon’s synthesis: match mission to mechanism—S3 for static starters, Amplify for authenticated ascents, Lambda for lean logic. His counsel: consult AWS’s compendium—getting-started guides, web app wisdom—curated for clarity.
His clarion: choose consciously, calibrating cost, celerity, scalability—AWS’s arsenal awaits.
Links:
[NDCOslo2024] Develop AI Agents with Semantic Kernel – Jakob Ehn
In the vanguard of generative paradigms, where language models orchestrate outcomes autonomously, Jakob Ehn, a seasoned solutions architect at Atea, illuminates Semantic Kernel’s symphony. A Microsoft MVP with a penchant for Azure and AI, Jakob unveils this open-source orchestrator—born in Microsoft’s copilot crucible—as a conduit for infusing intelligence into imperatives. His tutorial, threaded with live enactments, empowers .NET denizens to conjure agents that deliberate, delegate, and deliver, transcending prompts to proactive pursuits.
Jakob ignites with LLMs’ leap: from GPT’s generative gloss to agentic autonomy, where kernels coordinate calls, chaining capabilities contextually. Semantic Kernel, polyglot and potent, abstracts APIs into plugins, planners plot paths, memories mint moments—crafting copilots that converse, compute, and conclude sans ceaseless coding.
Foundations of Fusion: Kernel Configurations and Plugins
Semantic Kernel’s scaffold: a kernel encapsulating services—embeddings, chat completions—interfacing IConnectors for OpenAI or Azure. Jakob blueprints: var builder = Kernel.CreateBuilder(); builder.AddAzureOpenAIChatCompletion(…), yielding a kernel primed for prompts.
Plugins propel: native .NET assemblies or OpenAPI schemas, exposing functions as facets. Jakob instantiates: a weather plugin with GetForecastAsync, invoked via kernel.InvokeAsync. Semantic functions, YAML-yielded, infuse prompts with placeholders: “Current weather in {location}?”—blending blueprints with brains.
Memories memorialize: volatile or vectorized, persisting precedents for pertinence. Jakob’s vector store—Chroma—embeds episodes, retrieving resonances via similarity searches, enriching responses with recency.
Planners and Agents: Autonomous Assemblies
Planners pioneer paths: Sequential, Stepwise, or Action—dissecting directives into doables. Jakob’s Action planner: given “Book a flight,” it inventories functions—search, reserve—sequencing sans stalemates. Handles, he highlights, hallucination hurdles, grounding goals in grapples.
Agents amplify: collaborative cohorts, each expert in ethos—developer drafts, organizer oversees. Jakob’s ensemble: a proposal pipeline, where agents iterate abstracts, incorporating critiques conversationally. Semantic functions script sagas: “Revise to {limit} words, include {term}”—looping lucidly.
His demo: a conference copilot, soliciting sessions, surfacing summaries—agents alchemizing APIs into anecdotes.
Horizons and Hurdles: Refinements and Realities
Jakob tempers triumph: kernels kindle complexity—prompt precision, plugin parity. Yet, prospects gleam: multi-modal melds, enterprise embeddings. His behest: experiment, embracing Semantic Kernel’s scaffold to sculpt sentient solutions.
Links:
[KotlinConf2019] Ktor for Mobile Developers: Conquering the Server with Dan Kim
For many mobile developers, the thought of venturing into server-side development can be daunting, often perceived as a realm of unfamiliar languages, complex frameworks, and different programming paradigms. Dan Kim, an experienced developer, aimed to demystify this process at KotlinConf 2019 with his talk, “Ktor for Mobile Developers: Fear the server no more!”. He showcased Ktor, a Kotlin-based framework for building asynchronous servers and clients, as an accessible and powerful tool for mobile developers looking to create backend components for their applications. The official website for Ktor is ktor.io.
Dan Kim’s session was designed to demonstrate how existing Kotlin knowledge could be leveraged to easily build server-side applications with Ktor. He promised a practical, real-world example, walking attendees through everything needed to get a server up and running: authentication, data retrieval, data posting, and deployment, ultimately aiming to give mobile developers the confidence to build their own backend services.
Introducing Ktor: Simplicity and Power in Kotlin
Ktor is a framework built by JetBrains, designed from the ground up with Kotlin and coroutines in mind, making it inherently asynchronous and well-suited for building scalable network applications. Dan Kim introduced Ktor’s core concepts, such as its flexible pipeline architecture, routing capabilities, and features for handling HTTP requests and responses. A key appeal of Ktor for mobile developers is that it allows them to stay within the Kotlin ecosystem, using a language and paradigms they are already familiar with from Android development.
The presentation would have highlighted Ktor’s ease of use and minimal boilerplate. Unlike some larger, more opinionated server-side frameworks, Ktor offers a more unopinionated and lightweight approach, allowing developers to choose and configure only the features they need. This can include functionalities like authentication, content negotiation (e.g., for JSON or XML), templating engines, and session management, all installable as “features” or plugins within a Ktor application.
Building a Real-World Server-Side Component
The core of Dan Kim’s talk was a hands-on demonstration of building a server-side component. He aimed to build a RESTful API and a web application, complete with authentication, and deploy it to Google Cloud, all within an impressively small amount of code (around 350 lines, as he mentioned). This practical example would have covered essential aspects of backend development:
* Routing: Defining endpoints to handle different HTTP methods (GET, POST, etc.) and URL paths.
* Request Handling: Processing incoming requests, extracting parameters, and validating data.
* Authentication: Implementing mechanisms to secure endpoints and manage user identity, possibly integrating with external services.
* Data Interaction: Showing how to get data from and post data to other services or a database (though the specifics of database interaction might vary).
* Deployment: Walking through the process of deploying the Ktor application to a cloud platform like Google Cloud, making the backend accessible to mobile clients.
By tackling these common server-side tasks using Ktor and Kotlin, Dan aimed to alleviate the fears mobile developers might have about backend development and demonstrate that they already possess many of the necessary skills.
Empowering Mobile Developers to Go Full-Stack
The overarching message of Dan Kim’s presentation was one of empowerment. He sought to show that with Ktor, mobile developers no longer need to “fear the server”. The framework provides a gentle learning curve and a productive environment for building robust and efficient backend services. This capability is increasingly valuable as mobile applications become more sophisticated and often require custom backend logic to support their features.
Dan Kim’s practical demonstration, from basic Ktor setup to cloud deployment, was intended to give attendees a clear understanding of how to connect their own server-side components to virtually any API. By simplifying the backend development process, Ktor enables mobile developers to potentially take on more full-stack responsibilities, leading to greater control over their application’s entire architecture and a faster development cycle for new features. He hoped his session would provide the confidence needed for mobile developers to start building their own server-side solutions with Kotlin and Ktor.
Links:
[DevoxxPL2019] GraphQL in the Java Ecosystem: A Comprehensive Exploration
Lecturer
Vladimir Dejanović is a seasoned software professional with over a decade of experience in the IT industry, having contributed to diverse projects since 2006. As Senior Director of B2C Technology at PVH, a fashion technology firm overseeing brands like Tommy Hilfiger and Calvin Klein, he focuses on scalable systems and innovative solutions. Beyond his corporate role, Vladimir founded and leads the Amsterdam Java User Group, fostering community engagement in Java technologies. He is recognized as an Oracle Code One Star and Java Rockstar, frequently delivering presentations at international conferences on topics like GraphQL and Java development.
Abstract
This article delves into the intricacies of GraphQL as applied within Java environments, examining its specification, implementation strategies, and practical applications through code demonstrations. It analyzes the advantages of GraphQL over traditional REST APIs, such as enhanced query flexibility and schema validation, while addressing potential pitfalls like cyclic dependencies and security concerns. Drawing from real-world examples, the discussion highlights methodologies for schema design, resolver integration, and performance optimization, underscoring GraphQL’s role in modern API development and its implications for system architecture.
Understanding GraphQL: Beyond the Basics
GraphQL emerges as a pivotal specification in API design, originating from Facebook in 2015 to address inefficiencies in data fetching encountered during mobile application development. Unlike conventional REST APIs, which often result in over-fetching or under-fetching of data, GraphQL empowers clients to request precisely the information needed, thereby optimizing network usage and enhancing performance. The specification defines a query language that allows for declarative data retrieval, where clients specify the structure of the response, aligning closely with application requirements.
At its core, GraphQL is not a full-fledged framework but a set of guidelines that various languages implement differently. In Java, implementations like GraphQL Java provide the engine for processing queries, while tools such as GraphQL Java Kickstarters facilitate integration with existing infrastructures, such as Spring Boot. This flexibility means developers must be cognizant of implementation-specific nuances, including coverage of the specification and additional features not mandated by the core rules. For instance, while the specification mandates schema validation, implementations may vary in handling extensions like custom scalars or error propagation.
The schema definition language (SDL) stands out as GraphQL’s most potent feature, surpassing alternatives like OpenAPI in expressiveness. It requires a mandatory schema that describes types, fields, and relationships, ensuring both client and server adhere to a contract. Upon connection, the server transmits the schema, enabling clients to validate requests locally before transmission, which reduces invalid traffic and conserves resources. This schema-first approach, preferred for its mockability, allows teams to prototype APIs independently: backend developers define the schema, while frontend teams use mocks to simulate responses.
Consider a practical scenario involving a conference application with entities like attendees, speakers, and talks. The schema might define types as follows:
type Attendee {
id: ID!
name: String
}
type Speaker {
id: ID!
name: String
twitter: String
}
type Talk {
id: ID!
title: String
description: String
speakers: [Speaker]
}
Here, the exclamation mark denotes mandatory fields, and arrays indicate relationships. This structure not only documents the API but also enforces consistency, preventing outdated documentation—a common issue in REST environments.
Implementing Queries and Resolvers in Java
Transitioning to code, integrating GraphQL in Java involves wiring the schema to business logic. Using Spring Boot and GraphQL Java, one initializes a servlet mapped to “/graphql”, parsing the schema and registering resolvers. Resolvers act as the bridge, implementing interfaces like GraphQLQueryResolver for read operations.
For the conference example, a Query class might look like this:
@Component
public class Query implements GraphQLQueryResolver {
private final TalkService talkService;
private final SpeakerService speakerService;
private final AttendeeService attendeeService;
@RequiredArgsConstructor
public Query(TalkService talkService, SpeakerService speakerService, AttendeeService attendeeService) {
this.talkService = talkService;
this.speakerService = speakerService;
this.attendeeService = attendeeService;
}
public List<Talk> allTalks() {
return talkService.findAll();
}
public List<Speaker> allSpeakers() {
return speakerService.findAll();
}
public List<Attendee> allAttendees() {
return attendeeService.findAll();
}
}
This setup enables queries like fetching all talks with specific fields:
query {
allTalks {
id
title
description
speakers {
name
twitter
}
}
}
The response mirrors the query structure in JSON, promoting predictability. Clients can alias fields (e.g., renaming “title” to “myTitle”) or conditionally include them using directives like @include(if: $variable), where variables are passed separately for dynamic behavior.
Resolvers for relationships, such as linking talks to speakers, extend GraphQLResolver:
@Component
public class TalkResolver implements GraphQLResolver<Talk> {
private final SpeakerService speakerService;
@RequiredArgsConstructor
public TalkResolver(SpeakerService speakerService) {
this.speakerService = speakerService;
}
public List<Speaker> speakers(Talk talk) {
return speakerService.findAllSpeakersForTalk(talk);
}
}
This modular approach allows for granular control, but it introduces risks like cyclic queries if bidirectional links (e.g., speakers to talks) are added without safeguards. Such cycles can lead to infinite loops, necessitating depth limits during validation.
Mutations: Enabling Data Modification
While queries handle reads, mutations facilitate writes, mirroring CRUD operations but with GraphQL’s precision. Defined similarly in the schema:
type Mutation {
addTalk(input: TalkInput!): Talk
}
Mutations require explicit input types to encapsulate parameters, ensuring type safety. In Java, a Mutation resolver implements GraphQLMutationResolver:
@Component
public class Mutation implements GraphQLMutationResolver {
private final TalkService talkService;
@RequiredArgsConstructor
public Mutation(TalkService talkService) {
this.talkService = talkService;
}
public Talk addTalk(TalkInput input) {
// Logic to create and persist talk
return talkService.save(input.toTalk());
}
}
This method processes inputs, validates them, and returns the updated entity. Unlike queries, which can execute in parallel for optimization, mutations are sequential to maintain data integrity. Errors in mutations propagate similarly to queries, with customizable handlers to continue processing or halt execution.
The implications are profound: mutations reduce boilerplate compared to REST’s multiple endpoints, centralizing logic while allowing clients to request related data in the same response, such as fetching the newly added talk’s speakers.
Subscriptions: Real-Time Data Streams
Subscriptions introduce reactive capabilities, enabling server-push updates over WebSockets. The schema defines:
type Subscription {
scores(title: String!): Score
}
type Score {
title: String
score: Int
}
In Java, using Reactor for reactivity:
@Component
public class Subscription implements GraphQLSubscriptionResolver {
public Publisher<Score> scores(String title) {
return Flux.interval(Duration.ofSeconds(2))
.map(i -> Score.builder()
.title(title)
.score(ThreadLocalRandom.current().nextInt(1, 6))
.build());
}
}
This generates scores every two seconds, demonstrating backpressure handling to prevent client overload. Subscriptions transform static APIs into dynamic ones, ideal for live updates like conference feedback, though implementation varies—GraphQL Java uses WebSockets, but the specification leaves transport open.
Security and Performance Considerations
Security in GraphQL demands vigilance, as the schema’s public nature exposes potential attack vectors. Authentication and authorization occur via custom contexts:
public class MyGraphQLContext extends GraphQLContext {
private final User user;
public MyGraphQLContext(User user) {
this.user = user;
}
}
Resolvers access this context via DataFetchingEnvironment to enforce roles. For schema protection, directives or instrumentation filter visibility, though non-standard approaches risk interoperability.
Performance pitfalls include N+1 queries, mitigated by batching or caching in services. Instrumentation traces execution:
public class TracingInstrumentation extends SimpleInstrumentation {
@Override
public InstrumentationContext<ExecutionResult> beginExecution(InstrumentationExecutionParameters parameters) {
// Start timer, log query
return super.beginExecution(parameters);
}
}
Query complexity analysis during validation prevents denial-of-service attacks by capping depth or computational cost.
Schema management in large systems involves stitching or extensions to avoid monolithic files:
extend type Speaker {
twitter: String
}
This federates schemas across services, though conflicts require governance.
Implications for Modern Development
GraphQL’s client-centric model shifts power from servers, fostering agile development but requiring robust safeguards. In Java, its integration with Spring Boot streamlines adoption, yet demands awareness of implementation variances. By enabling precise data fetching and real-time interactions, it addresses REST’s limitations, promoting efficient, scalable architectures. Future specification enhancements, like improved subscription standards, promise broader applicability.